<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ExtensionBooster</title>
    <description>The latest articles on DEV Community by ExtensionBooster (@extensionbooster).</description>
    <link>https://dev.to/extensionbooster</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F158707%2F27211157-d026-407e-b9df-17252214baa2.webp</url>
      <title>DEV Community: ExtensionBooster</title>
      <link>https://dev.to/extensionbooster</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/extensionbooster"/>
    <language>en</language>
    <item>
      <title>Chrome Side Panel API: Build a Sidebar Extension (2026) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 08:00:11 +0000</pubDate>
      <link>https://dev.to/extensionbooster/chrome-side-panel-api-build-a-sidebar-extension-2026-extensionbooster-5gfc</link>
      <guid>https://dev.to/extensionbooster/chrome-side-panel-api-build-a-sidebar-extension-2026-extensionbooster-5gfc</guid>
      <description>&lt;h1&gt;
  
  
  Chrome Side Panel API: Build a Sidebar Extension (2026) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;UI design in Chrome extensions is where most developers struggle. After building several, here's what I've learned about making extensions look good and work well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The highlights
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chrome Side Panel API: Build a Sidebar Extension (2026) | ExtensionBooster You’re building a Chrome extension, and a popup feels wrong for it&lt;/li&gt;
&lt;li&gt;Your feature needs to stay open while the user reads a page, takes notes, or navigates between tabs&lt;/li&gt;
&lt;li&gt;Every time the popup closes, the workflow breaks&lt;/li&gt;
&lt;li&gt;You’ve tried injecting a sidebar with a content script, but it keeps fighting with page styles and breaks on half a dozen sites&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;Chrome Side Panel API: Build a Sidebar Extension (2026) | ExtensionBooster You’re building a Chrome extension, and a popup feels wrong for it. Your feature needs to stay open while the user reads a page, takes notes, or navigates between tabs. Every time the popup closes, the workflow breaks. You’ve tried injecting a sidebar with a content script, but it keeps fighting with page styles and breaks on half a dozen sites. The Chrome Side Panel API gives your extension a native, persistent sidebar that lives completely outside the page’s DOM. It shipped as a stable API in Chrome 114 (May 2023) and requires Manifest V3. What the Side Panel API Actually Is The Chrome Side Panel API ( chrome. sidePanel ) lets your extension render a full extension page in Chrome’s built-in side panel, the same panel Chrome uses for its own Reading List and Bookmarks features. A few things that make it different from what you’ve probably built before: It’s a full extension page, meaning it has complete access to all Chrome extension APIs. Unlike content scripts, there are no restrictions. It persists across tab navigation. The user can click through 10 different pages and your panel stays open, maintains state, and keeps running. It’s isolated from the host page’s CSS and JS. No style conflicts, no breakage on SPAs that rewrite the DOM. The user controls which side the panel docks on (left or right) in Chrome settings. Your extension doesn’t set that. Manifest Setup: Two Things You Need Getting the side panel working starts with two additions to manifest. Add "sidePanel" to your permissions array, and declare the side_panel key with a default_path. { "manifest_version" : 3 , "name" : "My Side Panel Extension" , "version" : "1. 0" , "permissions" : [ "sidePanel" ], "side_panel" : { "default_path" : "sidepanel. html" }, "background" : { "service_worker" : "background. js" }, "action" : {} } The default_path points to an HTML file at the root of your extension package. That file loads just like any other extension page. Give it its own CSS, its own JS, the works. Key: The "action" key is required in the manifest even if you don’t define a popup. setPanelBehavior won’t wire up the toolbar icon correctly. See the full manifest reference for other keys you might need alongside this. Making the Toolbar Icon Open the Panel By default, clicking your extension’s toolbar icon does nothing unless you define a popup. To make it open the side panel instead, call setPanelBehavior in your service worker: // background. addListener (() =&amp;gt; { chrome. setPanelBehavior ({ openPanelOnActionClick: true }); }); That’s it. One call, and clicking the toolbar icon toggles the panel open and closed. You’ll want this in onInstalled so it runs when the extension first loads (and after updates). Per-Tab Panels: Show Different Content Per Site The API shines when you need to show different panels depending on what tab the user is on. The setOptions method accepts an optional tabId. Pass it to scope a panel path (or enable/disable the panel) to a specific tab. js: show a special panel on github. addListener (( tabId , changeInfo , tab ) =&amp;gt; { if (changeInfo. == 'complete' ) return ; const isGithub = tab. setOptions ({ tabId, path: isGithub. html' , enabled: true , }); }); Omit tabId entirely to set a global default that applies when no per-tab override is set. The two layers compose cleanly: tab-level settings take priority over the global default. You can also disable the panel for a specific tab (pass enabled: false ). This is useful if your extension only makes sense on certain pages. Opening the Panel Programmatically Sometimes you want to open the panel from code rather than waiting for the user to click the toolbar icon. open() does this, but with one hard constraint: it must be called in direct response to a user gesture. Chrome blocks calls outside a user gesture context. This API is available from Chrome 116+.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Keep popup UI minimal — users close it fast if it's slow to load.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
      <category>api</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp; Ranked) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 07:11:56 +0000</pubDate>
      <link>https://dev.to/extensionbooster/top-10-ui-kits-for-chrome-extensions-in-2026-tested-ranked-extensionbooster-44lj</link>
      <guid>https://dev.to/extensionbooster/top-10-ui-kits-for-chrome-extensions-in-2026-tested-ranked-extensionbooster-44lj</guid>
      <description>&lt;h1&gt;
  
  
  Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;UI design in Chrome extensions is where most developers struggle. After building several, here's what I've learned about making extensions look good and work well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster Every “best React UI library” listicle you’ll find ranks the same kits: MUI, Chakra, Mantine, shadcn/ui&lt;/li&gt;
&lt;li&gt;And if you copy-paste that ranking into a Chrome extension, you’ll hit a wall the listicle never warned you about: your beautiful component library throws a Content Security Policy error and refuses to render&lt;/li&gt;
&lt;li&gt;Manifest V3 locks down what code can run, your content scripts fight the host page’s CSS, and your popup has to look good at 400 pixels wide&lt;/li&gt;
&lt;li&gt;Js dashboard can be the worst choice for an extension&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster Every “best React UI library” listicle you’ll find ranks the same kits: MUI, Chakra, Mantine, shadcn/ui. They’re written for normal web apps. And if you copy-paste that ranking into a Chrome extension, you’ll hit a wall the listicle never warned you about: your beautiful component library throws a Content Security Policy error and refuses to render. A browser extension is not a website. Manifest V3 locks down what code can run, your content scripts fight the host page’s CSS, and your popup has to look good at 400 pixels wide. The UI kit that’s perfect for a Next. js dashboard can be the worst choice for an extension. I rebuilt the same extension popup, options page, and content-script overlay across the major UI kits to see which ones survive contact with MV3. Here’s the ranked result, plus the one constraint that decides everything. Why a Chrome Extension UI Is Different (Read This First) Before the list, understand the four constraints that flip the rankings. Skip this and you’ll pick wrong. Manifest V3 Content Security Policy. Extension pages run under a strict default CSP: no remote code, no eval , and tight rules on inline styles. Any library that injects  tags at runtime (the CSS-in-JS approach used by Emotion and styled-components) can trip this unless you wire up a nonce. Worse, some components also set inline style=&amp;amp;quot;&amp;amp;quot; attributes that a nonce doesn’t cover, forcing you to weaken your CSP with style-src-attr &amp;amp;#39;unsafe-inline&amp;amp;#39;. If you care about a clean security posture (and the Chrome Web Store reviewers do, see our extension sandboxing and security guide ), runtime CSS-in-JS is a headache. Shadow DOM style isolation. When you inject UI into a third-party page via a content script , the host page’s CSS bleeds into your widget and your CSS bleeds into theirs. The fix is mounting inside a Shadow DOM root. But this matters for your kit choice: CSS-in-JS libraries inject styles into document. head , not your shadow root, so they break. Pre-compiled CSS (Tailwind output, CSS modules) can be injected as a string straight into the shadow root. Web components define their styles inside the shadow root natively. A toolbar popup is roughly 400 to 600 pixels wide and capped in height. Heavyweight component libraries built for full-page dashboards feel cramped. See our popup UI design best practices for layout patterns. Every kilobyte ships to the user and slows your popup’s first paint. A 300 KB component library is a luxury an extension can rarely afford. Read how to reduce extension bundle size for the full story. They’re why a kit that’s “S-tier for web” can be “avoid” for extensions. TL;DR: The Ranking at a Glance # UI kit Styling approach MV3 CSP safe. shadcn/ui: The Default Winner ui. com | MIT | Radix + Tailwind | React shadcn/ui isn’t a dependency you install, it’s components you copy into your own source tree. That single design decision makes it the best fit for extensions in 2026. The components are built on headless Radix primitives and styled with Tailwind, so they compile to static CSS. No runtime style injection. It just works under MV3 out of the box. Because the code lives in your repo, you tree-shake by definition: you only have the components you actually pasted in. A typical popup setup adds roughly 20 to 50 KB depending on how many components you pull. It crossed ~75,000 GitHub stars and became the default for new Tailwind and React projects, so the ecosystem (blocks, themes, AI tooling) is enormous. If you’re injecting shadcn UI into a host page via a content script, either compile with Tailwind v3 output or inject your compiled CSS through adoptedStyleSheets and use px units. For popup and options pages (not in a shadow root), Tailwind v4 is fine. Verdict: Start here for any React extension. Pair it with WXT and you have a modern, CSP-clean stack in minutes. DaisyUI: The Lightweight Champion daisyui. com | MIT | Tailwind plugin | Any framework DaisyUI is a Tailwind CSS plugin that ships semantic class names ( btn , card , modal ) and zero JavaScript. The entire library, every component and every theme, is about 34 KB of CSS. That’s the smallest footprint on this list, and for a popup where first paint speed is everything, that matters. It’s framework-agnostic because it’s just CSS. Use it with React, Vue, Svelte, or plain HTML in a vanilla extension. For content scripts, you inject those 34 KB into your shadow root as a string and you’re done, no document. -- Works in any extension, no JS runtime --&amp;amp;gt; &amp;amp;lt; button class = &amp;amp;quot;btn btn-primary&amp;amp;quot; &amp;amp;gt;Save&amp;amp;lt;/ button &amp;amp;gt; &amp;amp;lt; div class = &amp;amp;quot;card bg-base-100 shadow-md&amp;amp;quot; &amp;amp;gt;. &amp;amp;lt;/ div &amp;amp;gt; The trade-off: DaisyUI styles components but doesn’t manage ARIA roles or keyboard interaction for you. You supply the behavior (or layer it on with a headless primitive). For accessibility expectations, see our accessible extension guide. Verdict: The best choice when bundle size is your top priority, or when you’re not using React. HeroUI (Formerly NextUI): Polished and Modern heroui. com | MIT | Tailwind v4 | React If you want shadcn-level CSP safety but with a more opinionated, ready-made visual style, HeroUI is the pick. Note the name: NextUI rebranded to HeroUI in January 2025 to signal it’s for the whole React ecosystem, not just Next. The v3 line rebuilt on Tailwind v4 and React Aria Components, dropped Framer Motion for native CSS animations, and slimmed the bundle considerably versus v2. Because the output is compiled Tailwind CSS, it carries the same MV3-safe property as shadcn/ui (and the same Tailwind v4 @property caveat for shadow roots). The React Aria foundation means accessibility is handled properly out of the box, which is a genuine advantage over DaisyUI. npx @heroui/codemod@latest migrate # if you&amp;amp;#39;re moving off NextUI Verdict: Great when you want batteries-included, accessible components and don’t need shadcn’s pixel-level customizability. Radix Primitives + Headless UI: Bring Your Own Styles radix-ui. com | MIT | Headless | React (Headless UI also Vue) Radix Primitives is the unstyled, accessible foundation that shadcn/ui is built on. Headless UI (from the Tailwind team) plays the same role. Neither ships any CSS, which means zero CSP risk by definition: you provide all the styling with Tailwind or CSS modules, and you get rock-solid keyboard nav and focus management for free. You’d reach for these directly when you’re building a bespoke design system and don’t want shadcn’s pre-styled starting point. Each Radix package is small (roughly 4 to 15 KB gzipped) and you install only what you use. Verdict: The power-user choice for custom design systems. For most teams, shadcn/ui (which wraps these) is the faster road.&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;💡 &amp;lt;strong&amp;gt;Quick tip:&amp;lt;/strong&amp;gt; Keep popup UI minimal — users close it fast if it&amp;amp;#39;s slow to load.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="if-you-build-chrome-extensions" href="#if-you-build-chrome-extensions" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  If you build Chrome extensions
&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;You&amp;amp;#39;ll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href="https://extensionbooster.net"&amp;gt;ExtensionBooster&amp;lt;/a&amp;gt; has free versions of all of these — I keep it bookmarked for every extension project.&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
    </item>
    <item>
      <title>WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 07:04:57 +0000</pubDate>
      <link>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5eje</link>
      <guid>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5eje</guid>
      <description>&lt;h1&gt;
  
  
  WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;There's a gap between "it works" and "it's production-ready" in extension development. Here's how to close it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026&lt;/li&gt;
&lt;li&gt;| ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS&lt;/li&gt;
&lt;li&gt;But then you noticed the GitHub commit history going quiet&lt;/li&gt;
&lt;li&gt;You found a discussion thread asking whether the project is still alive&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026. | ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS. Fast, minimal, familiar Vite setup. But then you noticed the GitHub commit history going quiet. You found a discussion thread asking whether the project is still alive. You wondered if you should switch to WXT instead. That tension, CRXJS’s elegance vs. WXT’s momentum, is exactly what this post unpacks. By the end, you’ll know which one to use for your specific situation, with no hand-waving. What CRXJS Actually Is First: CRXJS ( @crxjs/vite-plugin ) is not a framework. You add it to a standard Vite project, one you configure yourself, and it adds two things: native HMR across popup, content scripts, and sidepanel, plus smart manifest handling that turns your manifest. ts into a fully typed entry point. ts import { defineConfig } from "vite" ; import { crx } from "@crxjs/vite-plugin" ; import manifest from ". config" ; export default defineConfig ({ plugins: [ crx ({ manifest })], }); That’s essentially all the CRXJS-specific code in your project. Everything else is plain Vite: React/Vue/Svelte via their standard plugins, TypeScript via ts-loader , bundling via Rollup. CRXJS intercepts the manifest, resolves entry points, and injects the HMR runtime. The latest release is around 2. 0 , with Vite 8 support landing mid-2026. The API surface is small and stable, which is both a selling point and the reason it doesn’t need constant updates. What WXT Actually Is WXT is a full framework. Its comparison page at wxt. dev/guide/resources/compare says it directly: file-based entrypoints, auto-imports, automatic manifest generation, a dev server with HMR, and first-party cross-browser builds to Chrome, Firefox, Edge, and Safari from a single codebase. wxt/ src/ entrypoints/ popup/index. ts You define entry points by creating files in entrypoints/. WXT reads the directory, generates the manifest, wires HMR, and produces browser-specific zips for distribution. ts you write yourself, WXT wraps Vite internally and exposes a wxt. The framework also ships: wxt/storage , type-safe wrapper over browser. Head-to-Head: The Comparison Table CRXJS WXT Type Vite plugin Full framework Manifest handling manifest. ts via defineManifest() Auto-generated from file structure + wxt. ts Best for Lightweight additions to existing Vite apps New projects, cross-browser, teams Is CRXJS Still Maintained in 2026. This is the question everyone asks. The honest answer: yes, but with reduced velocity. Development slowed noticeably through 2025 and into 2026. In response, the community organized, &lt;a class="mentioned-user" href="https://dev.to/colearendt"&gt;@colearendt&lt;/a&gt; joined as a CRXJS Maintenance Team Coordinator to keep the project going, and Vite 8 support was eventually added. The plugin isn’t abandoned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Chrome.storage.sync has stricter quotas than chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 06:05:44 +0000</pubDate>
      <link>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5ef4</link>
      <guid>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5ef4</guid>
      <description>&lt;h1&gt;
  
  
  WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;Building extensions requires piecing together different tools and approaches. Here's a concise guide to the essentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026&lt;/li&gt;
&lt;li&gt;| ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS&lt;/li&gt;
&lt;li&gt;But then you noticed the GitHub commit history going quiet&lt;/li&gt;
&lt;li&gt;You found a discussion thread asking whether the project is still alive&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026. | ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS. Fast, minimal, familiar Vite setup. But then you noticed the GitHub commit history going quiet. You found a discussion thread asking whether the project is still alive. You wondered if you should switch to WXT instead. That tension, CRXJS’s elegance vs. WXT’s momentum, is exactly what this post unpacks. By the end, you’ll know which one to use for your specific situation, with no hand-waving. What CRXJS Actually Is First: CRXJS ( @crxjs/vite-plugin ) is not a framework. You add it to a standard Vite project, one you configure yourself, and it adds two things: native HMR across popup, content scripts, and sidepanel, plus smart manifest handling that turns your manifest. ts into a fully typed entry point. ts import { defineConfig } from "vite" ; import { crx } from "@crxjs/vite-plugin" ; import manifest from ". config" ; export default defineConfig ({ plugins: [ crx ({ manifest })], }); That’s essentially all the CRXJS-specific code in your project. Everything else is plain Vite: React/Vue/Svelte via their standard plugins, TypeScript via ts-loader , bundling via Rollup. CRXJS intercepts the manifest, resolves entry points, and injects the HMR runtime. The latest release is around 2. 0 , with Vite 8 support landing mid-2026. The API surface is small and stable, which is both a selling point and the reason it doesn’t need constant updates. What WXT Actually Is WXT is a full framework. Its comparison page at wxt. dev/guide/resources/compare says it directly: file-based entrypoints, auto-imports, automatic manifest generation, a dev server with HMR, and first-party cross-browser builds to Chrome, Firefox, Edge, and Safari from a single codebase. wxt/ src/ entrypoints/ popup/index. ts You define entry points by creating files in entrypoints/. WXT reads the directory, generates the manifest, wires HMR, and produces browser-specific zips for distribution. ts you write yourself, WXT wraps Vite internally and exposes a wxt. The framework also ships: wxt/storage , type-safe wrapper over browser. Head-to-Head: The Comparison Table CRXJS WXT Type Vite plugin Full framework Manifest handling manifest. ts via defineManifest() Auto-generated from file structure + wxt. ts Best for Lightweight additions to existing Vite apps New projects, cross-browser, teams Is CRXJS Still Maintained in 2026. This is the question everyone asks. The honest answer: yes, but with reduced velocity. Development slowed noticeably through 2025 and into 2026. In response, the community organized, &lt;a class="mentioned-user" href="https://dev.to/colearendt"&gt;@colearendt&lt;/a&gt; joined as a CRXJS Maintenance Team Coordinator to keep the project going, and Vite 8 support was eventually added. The plugin isn’t abandoned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Chrome.storage.sync has stricter quotas than chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp; Ranked) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 06:02:38 +0000</pubDate>
      <link>https://dev.to/extensionbooster/top-10-ui-kits-for-chrome-extensions-in-2026-tested-ranked-extensionbooster-52db</link>
      <guid>https://dev.to/extensionbooster/top-10-ui-kits-for-chrome-extensions-in-2026-tested-ranked-extensionbooster-52db</guid>
      <description>&lt;h1&gt;
  
  
  Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;UI design in Chrome extensions is where most developers struggle. After building several, here's what I've learned about making extensions look good and work well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster Every “best React UI library” listicle you’ll find ranks the same kits: MUI, Chakra, Mantine, shadcn/ui&lt;/li&gt;
&lt;li&gt;And if you copy-paste that ranking into a Chrome extension, you’ll hit a wall the listicle never warned you about: your beautiful component library throws a Content Security Policy error and refuses to render&lt;/li&gt;
&lt;li&gt;Manifest V3 locks down what code can run, your content scripts fight the host page’s CSS, and your popup has to look good at 400 pixels wide&lt;/li&gt;
&lt;li&gt;Js dashboard can be the worst choice for an extension&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;Top 10 UI Kits for Chrome Extensions in 2026 (Tested &amp;amp; Ranked) | ExtensionBooster Every “best React UI library” listicle you’ll find ranks the same kits: MUI, Chakra, Mantine, shadcn/ui. They’re written for normal web apps. And if you copy-paste that ranking into a Chrome extension, you’ll hit a wall the listicle never warned you about: your beautiful component library throws a Content Security Policy error and refuses to render. A browser extension is not a website. Manifest V3 locks down what code can run, your content scripts fight the host page’s CSS, and your popup has to look good at 400 pixels wide. The UI kit that’s perfect for a Next. js dashboard can be the worst choice for an extension. I rebuilt the same extension popup, options page, and content-script overlay across the major UI kits to see which ones survive contact with MV3. Here’s the ranked result, plus the one constraint that decides everything. Why a Chrome Extension UI Is Different (Read This First) Before the list, understand the four constraints that flip the rankings. Skip this and you’ll pick wrong. Manifest V3 Content Security Policy. Extension pages run under a strict default CSP: no remote code, no eval , and tight rules on inline styles. Any library that injects  tags at runtime (the CSS-in-JS approach used by Emotion and styled-components) can trip this unless you wire up a nonce. Worse, some components also set inline style=&amp;amp;quot;&amp;amp;quot; attributes that a nonce doesn’t cover, forcing you to weaken your CSP with style-src-attr &amp;amp;#39;unsafe-inline&amp;amp;#39;. If you care about a clean security posture (and the Chrome Web Store reviewers do, see our extension sandboxing and security guide ), runtime CSS-in-JS is a headache. Shadow DOM style isolation. When you inject UI into a third-party page via a content script , the host page’s CSS bleeds into your widget and your CSS bleeds into theirs. The fix is mounting inside a Shadow DOM root. But this matters for your kit choice: CSS-in-JS libraries inject styles into document. head , not your shadow root, so they break. Pre-compiled CSS (Tailwind output, CSS modules) can be injected as a string straight into the shadow root. Web components define their styles inside the shadow root natively. A toolbar popup is roughly 400 to 600 pixels wide and capped in height. Heavyweight component libraries built for full-page dashboards feel cramped. See our popup UI design best practices for layout patterns. Every kilobyte ships to the user and slows your popup’s first paint. A 300 KB component library is a luxury an extension can rarely afford. Read how to reduce extension bundle size for the full story. They’re why a kit that’s “S-tier for web” can be “avoid” for extensions. TL;DR: The Ranking at a Glance # UI kit Styling approach MV3 CSP safe. shadcn/ui: The Default Winner ui. com | MIT | Radix + Tailwind | React shadcn/ui isn’t a dependency you install, it’s components you copy into your own source tree. That single design decision makes it the best fit for extensions in 2026. The components are built on headless Radix primitives and styled with Tailwind, so they compile to static CSS. No runtime style injection. It just works under MV3 out of the box. Because the code lives in your repo, you tree-shake by definition: you only have the components you actually pasted in. A typical popup setup adds roughly 20 to 50 KB depending on how many components you pull. It crossed ~75,000 GitHub stars and became the default for new Tailwind and React projects, so the ecosystem (blocks, themes, AI tooling) is enormous. If you’re injecting shadcn UI into a host page via a content script, either compile with Tailwind v3 output or inject your compiled CSS through adoptedStyleSheets and use px units. For popup and options pages (not in a shadow root), Tailwind v4 is fine. Verdict: Start here for any React extension. Pair it with WXT and you have a modern, CSP-clean stack in minutes. DaisyUI: The Lightweight Champion daisyui. com | MIT | Tailwind plugin | Any framework DaisyUI is a Tailwind CSS plugin that ships semantic class names ( btn , card , modal ) and zero JavaScript. The entire library, every component and every theme, is about 34 KB of CSS. That’s the smallest footprint on this list, and for a popup where first paint speed is everything, that matters. It’s framework-agnostic because it’s just CSS. Use it with React, Vue, Svelte, or plain HTML in a vanilla extension. For content scripts, you inject those 34 KB into your shadow root as a string and you’re done, no document. -- Works in any extension, no JS runtime --&amp;amp;gt; &amp;amp;lt; button class = &amp;amp;quot;btn btn-primary&amp;amp;quot; &amp;amp;gt;Save&amp;amp;lt;/ button &amp;amp;gt; &amp;amp;lt; div class = &amp;amp;quot;card bg-base-100 shadow-md&amp;amp;quot; &amp;amp;gt;. &amp;amp;lt;/ div &amp;amp;gt; The trade-off: DaisyUI styles components but doesn’t manage ARIA roles or keyboard interaction for you. You supply the behavior (or layer it on with a headless primitive). For accessibility expectations, see our accessible extension guide. Verdict: The best choice when bundle size is your top priority, or when you’re not using React. HeroUI (Formerly NextUI): Polished and Modern heroui. com | MIT | Tailwind v4 | React If you want shadcn-level CSP safety but with a more opinionated, ready-made visual style, HeroUI is the pick. Note the name: NextUI rebranded to HeroUI in January 2025 to signal it’s for the whole React ecosystem, not just Next. The v3 line rebuilt on Tailwind v4 and React Aria Components, dropped Framer Motion for native CSS animations, and slimmed the bundle considerably versus v2. Because the output is compiled Tailwind CSS, it carries the same MV3-safe property as shadcn/ui (and the same Tailwind v4 @property caveat for shadow roots). The React Aria foundation means accessibility is handled properly out of the box, which is a genuine advantage over DaisyUI. npx @heroui/codemod@latest migrate # if you&amp;amp;#39;re moving off NextUI Verdict: Great when you want batteries-included, accessible components and don’t need shadcn’s pixel-level customizability. Radix Primitives + Headless UI: Bring Your Own Styles radix-ui. com | MIT | Headless | React (Headless UI also Vue) Radix Primitives is the unstyled, accessible foundation that shadcn/ui is built on. Headless UI (from the Tailwind team) plays the same role. Neither ships any CSS, which means zero CSP risk by definition: you provide all the styling with Tailwind or CSS modules, and you get rock-solid keyboard nav and focus management for free. You’d reach for these directly when you’re building a bespoke design system and don’t want shadcn’s pre-styled starting point. Each Radix package is small (roughly 4 to 15 KB gzipped) and you install only what you use. Verdict: The power-user choice for custom design systems. For most teams, shadcn/ui (which wraps these) is the faster road.&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;💡 &amp;lt;strong&amp;gt;Quick tip:&amp;lt;/strong&amp;gt; Keep popup UI minimal — users close it fast if it&amp;amp;#39;s slow to load.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;hr&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="if-you-build-chrome-extensions" href="#if-you-build-chrome-extensions" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  If you build Chrome extensions
&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;You&amp;amp;#39;ll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href="https://extensionbooster.net"&amp;gt;ExtensionBooster&amp;lt;/a&amp;gt; has free versions of all of these — I keep it bookmarked for every extension project.&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reviews</category>
      <category>ui</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Developer's Guide to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 06:00:14 +0000</pubDate>
      <link>https://dev.to/extensionbooster/the-developers-guide-to-find-a-chrome-extension-by-its-id-3-easy-ways-extensionbooster-3kn2</link>
      <guid>https://dev.to/extensionbooster/the-developers-guide-to-find-a-chrome-extension-by-its-id-3-easy-ways-extensionbooster-3kn2</guid>
      <description>&lt;h1&gt;
  
  
  How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;Chrome extension development has a reputation for being trickier than it looks. After spending time with this topic, here's what actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The essentials
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster You’re staring at a string like cjpalhdlnbpafiamejdnhcphjbkeiagm with zero context&lt;/li&gt;
&lt;li&gt;Maybe you’re auditing a managed device and need to know what that extension actually does before you allow or block it&lt;/li&gt;
&lt;li&gt;Whatever brought you here, the answer is the same: every installed Chrome extension carries a unique ID, and that ID is your key to finding everything about it&lt;/li&gt;
&lt;li&gt;Here’s how to do it, in three ways, starting with the fastest&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster You’re staring at a string like cjpalhdlnbpafiamejdnhcphjbkeiagm with zero context. Maybe it showed up in a security log. Maybe a coworker pasted it in Slack. Maybe you’re auditing a managed device and need to know what that extension actually does before you allow or block it. Whatever brought you here, the answer is the same: every installed Chrome extension carries a unique ID, and that ID is your key to finding everything about it. Here’s how to do it, in three ways, starting with the fastest. What a Chrome extension ID actually is Before you go looking, it helps to know what you’re looking at. Every Chrome extension has a 32-character ID made up only of lowercase letters a through p (no numbers, no other characters). It looks something like cjpalhdlnbpafiamejdnhcphjbkeiagm. That string isn’t random, it’s derived from the extension’s public key when it’s first submitted to the Chrome Web Store. The practical upshot: the ID is permanent for a published extension. It doesn’t change between version 1. An extension’s icon, name, and description can be completely overhauled and the ID stays the same. There’s one catch worth knowing: an unpacked extension (one you load locally from a folder via Developer mode) gets a temporary, randomly assigned ID each time, unless the developer sets a key field in the manifest. Published extensions don’t have this problem. If you’re dealing with a CRX you loaded yourself, the ID might not match anything in the store. # Published extension ID, stable forever cjpalhdlnbpafiamejdnhcphjbkeiagm # The full Web Store URL pattern with that ID &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail// # Or the shorter form, Chrome resolves either &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ Where do I find an extension’s ID. Two reliable places: From chrome://extensions : Open a new tab, type chrome://extensions in the address bar, and hit Enter. Toggle Developer mode on (top-right corner of the page). Every installed extension now shows its ID directly beneath its name and version. From the Chrome Web Store URL: If you’re on the extension’s listing page, look at the URL. It ends with the 32-character ID after the final slash: &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ that's the ID Copy either one and you’re ready to look it up. Why you’d want to find an extension by ID A few common situations where you need to go from ID to extension: IT and enterprise auditing: You have a list of extension IDs deployed via policy. You need to confirm what each one does, who publishes it, and whether any have been removed from the store (a red flag). Security and incident response: A suspicious process or network request traces back to a browser extension ID. You need the name, publisher, and permission list fast. Competitor research: You found an extension ID in a CRX file or a competitor’s browser profile. You want to understand what it does before you build against it. Verifying a CRX before installing: Someone sent you a. You want to confirm it maps to a legitimate store listing before you install anything. Recovering a delisted extension: An extension you relied on disappeared from the store. The ID is still in your chrome://extensions list. A third-party lookup might still have archived metadata. Method 1: Build the Chrome Web Store URL yourself This is the fastest method when the extension is still publicly listed. Take your 32-character ID and plug it directly into this URL pattern: &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ Replace &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; with your actual string. If the extension is published and not unlisted, Chrome will redirect you to the full listing page, name, icon, description, publisher, ratings, and permission list all visible. Works great for: any currently published, publicly listed extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 05:05:37 +0000</pubDate>
      <link>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-3mpf</link>
      <guid>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-3mpf</guid>
      <description>&lt;h1&gt;
  
  
  WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;If you've worked with Chrome extensions, you know the details matter. Here's a breakdown that cuts through the noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026&lt;/li&gt;
&lt;li&gt;| ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS&lt;/li&gt;
&lt;li&gt;But then you noticed the GitHub commit history going quiet&lt;/li&gt;
&lt;li&gt;You found a discussion thread asking whether the project is still alive&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026. | ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS. Fast, minimal, familiar Vite setup. But then you noticed the GitHub commit history going quiet. You found a discussion thread asking whether the project is still alive. You wondered if you should switch to WXT instead. That tension, CRXJS’s elegance vs. WXT’s momentum, is exactly what this post unpacks. By the end, you’ll know which one to use for your specific situation, with no hand-waving. What CRXJS Actually Is First: CRXJS ( @crxjs/vite-plugin ) is not a framework. You add it to a standard Vite project, one you configure yourself, and it adds two things: native HMR across popup, content scripts, and sidepanel, plus smart manifest handling that turns your manifest. ts into a fully typed entry point. ts import { defineConfig } from "vite" ; import { crx } from "@crxjs/vite-plugin" ; import manifest from ". config" ; export default defineConfig ({ plugins: [ crx ({ manifest })], }); That’s essentially all the CRXJS-specific code in your project. Everything else is plain Vite: React/Vue/Svelte via their standard plugins, TypeScript via ts-loader , bundling via Rollup. CRXJS intercepts the manifest, resolves entry points, and injects the HMR runtime. The latest release is around 2. 0 , with Vite 8 support landing mid-2026. The API surface is small and stable, which is both a selling point and the reason it doesn’t need constant updates. What WXT Actually Is WXT is a full framework. Its comparison page at wxt. dev/guide/resources/compare says it directly: file-based entrypoints, auto-imports, automatic manifest generation, a dev server with HMR, and first-party cross-browser builds to Chrome, Firefox, Edge, and Safari from a single codebase. wxt/ src/ entrypoints/ popup/index. ts You define entry points by creating files in entrypoints/. WXT reads the directory, generates the manifest, wires HMR, and produces browser-specific zips for distribution. ts you write yourself, WXT wraps Vite internally and exposes a wxt. The framework also ships: wxt/storage , type-safe wrapper over browser. Head-to-Head: The Comparison Table CRXJS WXT Type Vite plugin Full framework Manifest handling manifest. ts via defineManifest() Auto-generated from file structure + wxt. ts Best for Lightweight additions to existing Vite apps New projects, cross-browser, teams Is CRXJS Still Maintained in 2026. This is the question everyone asks. The honest answer: yes, but with reduced velocity. Development slowed noticeably through 2025 and into 2026. In response, the community organized, &lt;a class="mentioned-user" href="https://dev.to/colearendt"&gt;@colearendt&lt;/a&gt; joined as a CRXJS Maintenance Team Coordinator to keep the project going, and Vite 8 support was eventually added. The plugin isn’t abandoned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Chrome.storage.sync has stricter quotas than chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Chrome Extensions on Android in 2026: What Actually Works | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 05:02:38 +0000</pubDate>
      <link>https://dev.to/extensionbooster/chrome-extensions-on-android-in-2026-what-actually-works-extensionbooster-53mp</link>
      <guid>https://dev.to/extensionbooster/chrome-extensions-on-android-in-2026-what-actually-works-extensionbooster-53mp</guid>
      <description>&lt;h1&gt;
  
  
  Chrome Extensions on Android in 2026: What Actually Works | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;Chrome extensions on Android is a different beast. Here's what works and what doesn't in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The highlights
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chrome Extensions on Android in 2026: What Actually Works | ExtensionBooster No, Chrome for Android still doesn’t support extensions&lt;/li&gt;
&lt;li&gt;If you searched “chrome extensions android” hoping for good news on standard phones, I’m sorry to disappoint you, but there are real options that work today, and one very interesting thing Google is building for tomorrow&lt;/li&gt;
&lt;li&gt;Can You Install Chrome Extensions on Android&lt;/li&gt;
&lt;li&gt;The mobile Chrome app Google ships on phones and tablets has no extension support, full stop&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;Chrome Extensions on Android in 2026: What Actually Works | ExtensionBooster No, Chrome for Android still doesn’t support extensions. It’s 2026 and that hasn’t changed. If you searched “chrome extensions android” hoping for good news on standard phones, I’m sorry to disappoint you, but there are real options that work today, and one very interesting thing Google is building for tomorrow. Let’s go through all of it honestly. Can You Install Chrome Extensions on Android. Not on standard Chrome for Android. The mobile Chrome app Google ships on phones and tablets has no extension support, full stop. There’s no hidden menu, no developer flag, no workaround. Google has never offered it. If you open the Chrome Web Store on your Android phone, you’ll see a message telling you extensions aren’t available for your device. That page has looked the same for years. So why do so many people keep searching for this. Some other browsers built on Chromium do. Browsers That Actually Support Extensions on Android Today Here’s the honest picture as of mid-2026. Browser Extension Support Source Notes Chrome for Android None Chrome Web Store Official; no extension support Firefox for Android Yes (official) addons. It’s official, it’s backed by Mozilla, and you install add-ons directly from addons. org/android/ , a curated catalog that includes uBlock Origin, Bitwarden, Dark Reader, and many others. If you want extensions on Android without dealing with unofficial Chromium forks, this is where to start. Kiwi Browser was the answer for years. It was a Chromium-based browser that let you install Chrome extensions directly from the Chrome Web Store, and it worked remarkably well. If you’re reading an older guide that recommends Kiwi, that guide is out of date. Quetta and Helium are the most credible Kiwi replacements right now. Both are Chromium forks that support Manifest V3 extensions from the Chrome Web Store. They’re smaller projects, so do your own research before making them your daily driver, but they’re real, working options. Yandex Browser supports Chrome extensions and has been doing so for years. The extension compatibility is solid. The concern some users have is that it’s made by a Russian company, which matters for your privacy calculus. Microsoft Edge Canary on Android has experimental extension support, but “experimental” means it can break between builds. Don’t rely on it for anything important. Will Chrome Ever Add Extensions on Android Phones. This is where it gets interesting, and where you need to read carefully, because the answer is “sort of, but probably not for your phone. ” Google is actively building a desktop Chrome build for Android. Android Authority reported in June 2025 that this build can install extensions directly from the Chrome Web Store. But here’s the catch: this desktop Chrome build is aimed at desktop-class Android hardware , think Android-powered PCs, foldables used in desktop mode, or Chromebook-style devices running Android. It is not being developed for regular phones and tablets through normal channels. Google has not announced any plans to bring extension support to the Chrome app that regular Android phone users install from the Play Store. The desktop Android build and the mobile Chrome app are different products targeting different use cases. So: extensions on Chrome for Android are coming, in the sense that Google is building the capability. But it’s aimed at a specific hardware category, not at solving the “I want uBlock Origin on my phone” problem. Key takeaway for users: Don’t hold your breath waiting for official extension support in standard Chrome on Android. Use Firefox for Android if you want extensions today, or explore Quetta or Helium if you specifically need Chrome Web Store access. Firefox for Android: The Most Legitimate Route If you want extensions on your Android phone right now, Firefox for Android is the most trustworthy path. Here’s why: Mozilla officially supports and maintains the add-on ecosystem for Android. Extensions go through a review process at addons.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Chrome Extension Content Scripts: Manifest V3 Guide (2026) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 04:02:48 +0000</pubDate>
      <link>https://dev.to/extensionbooster/chrome-extension-content-scripts-manifest-v3-guide-2026-extensionbooster-2d2g</link>
      <guid>https://dev.to/extensionbooster/chrome-extension-content-scripts-manifest-v3-guide-2026-extensionbooster-2d2g</guid>
      <description>&lt;h1&gt;
  
  
  Chrome Extension Content Scripts: Manifest V3 Guide (2026) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;UI design in Chrome extensions is where most developers struggle. After building several, here's what I've learned about making extensions look good and work well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The essentials
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chrome Extension Content Scripts: Manifest V3 Guide (2026) | ExtensionBooster You’ve spent two hours debugging why your content script can’t read a page variable&lt;/li&gt;
&lt;li&gt;You’ve confirmed the variable exists using DevTools&lt;/li&gt;
&lt;li&gt;Then it hits you: your content script runs in an isolated world&lt;/li&gt;
&lt;li&gt;The page’s JavaScript and your script are sharing the same DOM but living in completely separate JavaScript contexts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;Chrome Extension Content Scripts: Manifest V3 Guide (2026) | ExtensionBooster You’ve spent two hours debugging why your content script can’t read a page variable. You’ve confirmed the variable exists using DevTools. You’ve triple-checked the selector. Then it hits you: your content script runs in an isolated world. It literally cannot see that variable. The page’s JavaScript and your script are sharing the same DOM but living in completely separate JavaScript contexts. That isolation is not a bug. But knowing when it helps you, and when it fights you, is what separates a working extension from a frustrating one. This guide covers everything you need: how the two execution worlds work, every injection method, the chrome. scripting API, match patterns, and a practical section on calling chrome. downloads from a content script context. Isolated World vs Main World: The Core Concept When your content script runs on a page, Chrome places it in an isolated world by default. Picture two people working at the same desk (the DOM) but wearing noise-canceling headphones. They can both move the same papers (DOM nodes), but they can’t hear each other’s conversations (JavaScript variables and functions). Concretely: Your content script has its own JavaScript heap. It shares document and window. document for DOM manipulation. &lt;strong&gt;data&lt;/strong&gt; , or any variable the page’s own scripts set. The page cannot call your functions or access your variables. This separation is what lets Chrome extensions work safely on any site. Your extension code won’t accidentally collide with the site’s libraries, and a malicious site can’t hijack your extension’s logic. Here’s the comparison you’ll want to bookmark: Isolated World (default) Main World ( world: 'MAIN' ) JS context Separate from page Shared with page Access page variables No Yes Page can access your code No Yes chrome. dom Almost none Messaging to service worker Yes No (must use custom events or postMessage) Stable since Always Chrome 111 Use when Most cases Interacting with page JS (e. , SPA state, third-party SDKs) Gotcha: When you switch to world: 'MAIN' , you gain access to page JS but lose access to most Chrome APIs. ) from a main-world script. Use a coordinating isolated-world script that listens for window. postMessage events from your main-world script. Static Injection: Declaring Scripts in manifest. json The simplest way to inject a content script is a static declaration in your manifest. Chrome reads this at install time and injects automatically on matching pages. { "manifest_version" : 3 , "name" : "My Extension" , "version" : "1. 0" , "content_scripts" : [ { "matches" : [ "https://&lt;em&gt;. com/&lt;/em&gt;" ], "js" : [ "content. css" ], "run_at" : "document_idle" , "world" : "ISOLATED" , "all_frames" : false } ] } The key fields: matches : Array of match patterns. Controls which URLs get your script. "&lt;em&gt;://&lt;/em&gt;/&lt;em&gt;" covers all HTTP/HTTPS; "" adds file:// and more. Broad patterns trigger extra scrutiny in Chrome Web Store review. js : Array of script files, injected in order. css : Stylesheets injected before the DOM is ready (before document_start ). "document_idle" (default) fires after the page’s DOMContentLoaded and a short grace period. "document_start" fires before any DOM is parsed. "document_end" fires after DOM is ready but before sub-resources (images, scripts) finish loading. world : "ISOLATED" (default) or "MAIN". all_frames : Default false. Set true to inject into iframes too. Static injection is ideal for extensions that always need to run on specific sites. The content script loads automatically; no user action required. scripting Sometimes you don’t want a script running on every page load. Maybe you inject on demand when the user clicks the extension icon, or conditionally based on page content. You’ll need these permissions in your manifest: { "permissions" : [ "scripting" ], "host_permissions" : [ "https://&lt;/em&gt;. com/&lt;em&gt;" ] } Or use "activeTab" instead of broad host permissions for click-triggered injection. activeTab grants temporary access to the currently active tab when the user invokes your extension. One-off injection with executeScript // From your service worker or popup async function injectOnCurrentTab () { const [ tab ] = await chrome. query ({ active: true , currentWindow: true }); await chrome. executeScript ({ target: { tabId: tab. js" ], world: "ISOLATED" // or "MAIN" }); } You can also inject a function directly instead of a file: await chrome. executeScript ({ target: { tabId: tab. id }, func : () =&amp;gt; { document. background = "red" ; } }); Note: the injected function runs in an isolated context. Variables from the surrounding service worker closure are not available inside func. Pass data via the args parameter if needed. Persistent registration with registerContentScripts For scripts that should persist across browser restarts (similar to static injection but set up at runtime): await chrome. registerContentScripts ([{ id: "my-script" , matches: [ "https://&lt;/em&gt;. js" ], runAt: "document_idle" , world: "ISOLATED" }]); You can update or unregister these later with chrome. updateContentScripts and chrome. scripting reference for all options.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Keep popup UI minimal — users close it fast if it's slow to load.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 03:02:39 +0000</pubDate>
      <link>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-3h2b</link>
      <guid>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-3h2b</guid>
      <description>&lt;h1&gt;
  
  
  WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;Chrome extension development has a reputation for being trickier than it looks. After spending time with this topic, here's what actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026&lt;/li&gt;
&lt;li&gt;| ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS&lt;/li&gt;
&lt;li&gt;But then you noticed the GitHub commit history going quiet&lt;/li&gt;
&lt;li&gt;You found a discussion thread asking whether the project is still alive&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026. | ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS. Fast, minimal, familiar Vite setup. But then you noticed the GitHub commit history going quiet. You found a discussion thread asking whether the project is still alive. You wondered if you should switch to WXT instead. That tension, CRXJS’s elegance vs. WXT’s momentum, is exactly what this post unpacks. By the end, you’ll know which one to use for your specific situation, with no hand-waving. What CRXJS Actually Is First: CRXJS ( @crxjs/vite-plugin ) is not a framework. You add it to a standard Vite project, one you configure yourself, and it adds two things: native HMR across popup, content scripts, and sidepanel, plus smart manifest handling that turns your manifest. ts into a fully typed entry point. ts import { defineConfig } from "vite" ; import { crx } from "@crxjs/vite-plugin" ; import manifest from ". config" ; export default defineConfig ({ plugins: [ crx ({ manifest })], }); That’s essentially all the CRXJS-specific code in your project. Everything else is plain Vite: React/Vue/Svelte via their standard plugins, TypeScript via ts-loader , bundling via Rollup. CRXJS intercepts the manifest, resolves entry points, and injects the HMR runtime. The latest release is around 2. 0 , with Vite 8 support landing mid-2026. The API surface is small and stable, which is both a selling point and the reason it doesn’t need constant updates. What WXT Actually Is WXT is a full framework. Its comparison page at wxt. dev/guide/resources/compare says it directly: file-based entrypoints, auto-imports, automatic manifest generation, a dev server with HMR, and first-party cross-browser builds to Chrome, Firefox, Edge, and Safari from a single codebase. wxt/ src/ entrypoints/ popup/index. ts You define entry points by creating files in entrypoints/. WXT reads the directory, generates the manifest, wires HMR, and produces browser-specific zips for distribution. ts you write yourself, WXT wraps Vite internally and exposes a wxt. The framework also ships: wxt/storage , type-safe wrapper over browser. Head-to-Head: The Comparison Table CRXJS WXT Type Vite plugin Full framework Manifest handling manifest. ts via defineManifest() Auto-generated from file structure + wxt. ts Best for Lightweight additions to existing Vite apps New projects, cross-browser, teams Is CRXJS Still Maintained in 2026. This is the question everyone asks. The honest answer: yes, but with reduced velocity. Development slowed noticeably through 2025 and into 2026. In response, the community organized, &lt;a class="mentioned-user" href="https://dev.to/colearendt"&gt;@colearendt&lt;/a&gt; joined as a CRXJS Maintenance Team Coordinator to keep the project going, and Vite 8 support was eventually added. The plugin isn’t abandoned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Chrome.storage.sync has stricter quotas than chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Essential: Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 02:05:45 +0000</pubDate>
      <link>https://dev.to/extensionbooster/essential-find-a-chrome-extension-by-its-id-3-easy-ways-extensionbooster-4p0n</link>
      <guid>https://dev.to/extensionbooster/essential-find-a-chrome-extension-by-its-id-3-easy-ways-extensionbooster-4p0n</guid>
      <description>&lt;h1&gt;
  
  
  How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;If you've worked with Chrome extensions, you know the details matter. Here's a breakdown that cuts through the noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The essentials
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster You’re staring at a string like cjpalhdlnbpafiamejdnhcphjbkeiagm with zero context&lt;/li&gt;
&lt;li&gt;Maybe you’re auditing a managed device and need to know what that extension actually does before you allow or block it&lt;/li&gt;
&lt;li&gt;Whatever brought you here, the answer is the same: every installed Chrome extension carries a unique ID, and that ID is your key to finding everything about it&lt;/li&gt;
&lt;li&gt;Here’s how to do it, in three ways, starting with the fastest&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;How to Find a Chrome Extension by Its ID (3 Easy Ways) | ExtensionBooster You’re staring at a string like cjpalhdlnbpafiamejdnhcphjbkeiagm with zero context. Maybe it showed up in a security log. Maybe a coworker pasted it in Slack. Maybe you’re auditing a managed device and need to know what that extension actually does before you allow or block it. Whatever brought you here, the answer is the same: every installed Chrome extension carries a unique ID, and that ID is your key to finding everything about it. Here’s how to do it, in three ways, starting with the fastest. What a Chrome extension ID actually is Before you go looking, it helps to know what you’re looking at. Every Chrome extension has a 32-character ID made up only of lowercase letters a through p (no numbers, no other characters). It looks something like cjpalhdlnbpafiamejdnhcphjbkeiagm. That string isn’t random, it’s derived from the extension’s public key when it’s first submitted to the Chrome Web Store. The practical upshot: the ID is permanent for a published extension. It doesn’t change between version 1. An extension’s icon, name, and description can be completely overhauled and the ID stays the same. There’s one catch worth knowing: an unpacked extension (one you load locally from a folder via Developer mode) gets a temporary, randomly assigned ID each time, unless the developer sets a key field in the manifest. Published extensions don’t have this problem. If you’re dealing with a CRX you loaded yourself, the ID might not match anything in the store. # Published extension ID, stable forever cjpalhdlnbpafiamejdnhcphjbkeiagm # The full Web Store URL pattern with that ID &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail// # Or the shorter form, Chrome resolves either &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ Where do I find an extension’s ID. Two reliable places: From chrome://extensions : Open a new tab, type chrome://extensions in the address bar, and hit Enter. Toggle Developer mode on (top-right corner of the page). Every installed extension now shows its ID directly beneath its name and version. From the Chrome Web Store URL: If you’re on the extension’s listing page, look at the URL. It ends with the 32-character ID after the final slash: &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ that's the ID Copy either one and you’re ready to look it up. Why you’d want to find an extension by ID A few common situations where you need to go from ID to extension: IT and enterprise auditing: You have a list of extension IDs deployed via policy. You need to confirm what each one does, who publishes it, and whether any have been removed from the store (a red flag). Security and incident response: A suspicious process or network request traces back to a browser extension ID. You need the name, publisher, and permission list fast. Competitor research: You found an extension ID in a CRX file or a competitor’s browser profile. You want to understand what it does before you build against it. Verifying a CRX before installing: Someone sent you a. You want to confirm it maps to a legitimate store listing before you install anything. Recovering a delisted extension: An extension you relied on disappeared from the store. The ID is still in your chrome://extensions list. A third-party lookup might still have archived metadata. Method 1: Build the Chrome Web Store URL yourself This is the fastest method when the extension is still publicly listed. Take your 32-character ID and plug it directly into this URL pattern: &lt;a href="https://chromewebstore" rel="noopener noreferrer"&gt;https://chromewebstore&lt;/a&gt;. com/detail/ Replace &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; with your actual string. If the extension is published and not unlisted, Chrome will redirect you to the full listing page, name, icon, description, publisher, ratings, and permission list all visible. Works great for: any currently published, publicly listed extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster</title>
      <dc:creator>ExtensionBooster</dc:creator>
      <pubDate>Sat, 04 Jul 2026 01:03:46 +0000</pubDate>
      <link>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5d</link>
      <guid>https://dev.to/extensionbooster/wxt-vs-crxjs-which-extension-framework-wins-in-2026-extensionbooster-5d</guid>
      <description>&lt;h1&gt;
  
  
  WXT vs CRXJS: Which Extension Framework Wins in 2026? | ExtensionBooster
&lt;/h1&gt;

&lt;p&gt;The Chrome extension ecosystem moves fast. Here's a practical look at what works and what doesn't in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026&lt;/li&gt;
&lt;li&gt;| ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS&lt;/li&gt;
&lt;li&gt;But then you noticed the GitHub commit history going quiet&lt;/li&gt;
&lt;li&gt;You found a discussion thread asking whether the project is still alive&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Here's the thing
&lt;/h2&gt;

&lt;p&gt;WXT vs CRXJS: Which Extension Framework Wins in 2026. | ExtensionBooster If you started a new Chrome extension project last year, you probably Googled “vite chrome extension” and landed on CRXJS. Fast, minimal, familiar Vite setup. But then you noticed the GitHub commit history going quiet. You found a discussion thread asking whether the project is still alive. You wondered if you should switch to WXT instead. That tension, CRXJS’s elegance vs. WXT’s momentum, is exactly what this post unpacks. By the end, you’ll know which one to use for your specific situation, with no hand-waving. What CRXJS Actually Is First: CRXJS ( @crxjs/vite-plugin ) is not a framework. You add it to a standard Vite project, one you configure yourself, and it adds two things: native HMR across popup, content scripts, and sidepanel, plus smart manifest handling that turns your manifest. ts into a fully typed entry point. ts import { defineConfig } from "vite" ; import { crx } from "@crxjs/vite-plugin" ; import manifest from ". config" ; export default defineConfig ({ plugins: [ crx ({ manifest })], }); That’s essentially all the CRXJS-specific code in your project. Everything else is plain Vite: React/Vue/Svelte via their standard plugins, TypeScript via ts-loader , bundling via Rollup. CRXJS intercepts the manifest, resolves entry points, and injects the HMR runtime. The latest release is around 2. 0 , with Vite 8 support landing mid-2026. The API surface is small and stable, which is both a selling point and the reason it doesn’t need constant updates. What WXT Actually Is WXT is a full framework. Its comparison page at wxt. dev/guide/resources/compare says it directly: file-based entrypoints, auto-imports, automatic manifest generation, a dev server with HMR, and first-party cross-browser builds to Chrome, Firefox, Edge, and Safari from a single codebase. wxt/ src/ entrypoints/ popup/index. ts You define entry points by creating files in entrypoints/. WXT reads the directory, generates the manifest, wires HMR, and produces browser-specific zips for distribution. ts you write yourself, WXT wraps Vite internally and exposes a wxt. The framework also ships: wxt/storage , type-safe wrapper over browser. Head-to-Head: The Comparison Table CRXJS WXT Type Vite plugin Full framework Manifest handling manifest. ts via defineManifest() Auto-generated from file structure + wxt. ts Best for Lightweight additions to existing Vite apps New projects, cross-browser, teams Is CRXJS Still Maintained in 2026. This is the question everyone asks. The honest answer: yes, but with reduced velocity. Development slowed noticeably through 2025 and into 2026. In response, the community organized, &lt;a class="mentioned-user" href="https://dev.to/colearendt"&gt;@colearendt&lt;/a&gt; joined as a CRXJS Maintenance Team Coordinator to keep the project going, and Vite 8 support was eventually added. The plugin isn’t abandoned.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Quick tip:&lt;/strong&gt; Chrome.storage.sync has stricter quotas than chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  If you build Chrome extensions
&lt;/h2&gt;

&lt;p&gt;You'll eventually need tools for icons, screenshots, MV2→MV3 conversion, and bundle analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://extensionbooster.net" rel="noopener noreferrer"&gt;ExtensionBooster&lt;/a&gt; has free versions of all of these — I keep it bookmarked for every extension project.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
