# How a Chrome Extension DevTools Panel Integrates with Chrome's Built-in DevTools

> Learn how a Chrome extension devtools panel integrates with Chrome's built-in DevTools by registering a new tab via the manifest and chrome.devtools.panels.create API.

- Repository: [JongHak Seo/chrome-extension-boilerplate-react-vite](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite)
- Tags: internals
- Published: 2026-03-05

---

**A Chrome extension adds a custom DevTools panel by declaring a `devtools_page` in the manifest, which calls `chrome.devtools.panels.create()` to register a new tab inside Chrome's native DevTools interface.**

The `jonghakseo/chrome-extension-boilerplate-react-vite` repository demonstrates a complete implementation of how a devtools panel integrates with Chrome's built-in DevTools using a React-based architecture. This integration relies on three coordinated components: the manifest declaration, the DevTools page script, and the panel UI application.

## The Three-Core Architecture

The integration follows a specific pipeline defined by Chrome's extension API. Each component serves a distinct role in bridging the extension with Chrome's native DevTools environment.

| Component | Role | Source File |
|-----------|------|-------------|
| **Manifest** | Declares the `devtools_page` entry point | [`chrome-extension/manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts) (line 72) |
| **DevTools Page** | Executes `chrome.devtools.panels.create()` | [`pages/devtools/src/index.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools/src/index.ts) |
| **Panel UI** | Renders the React application inside the new panel | [`pages/devtools-panel/src/index.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools-panel/src/index.tsx) and [`Panel.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/Panel.tsx) |

## Step 1: Declaring the DevTools Page in manifest.ts

Chrome requires a `devtools_page` entry in the extension manifest to initialize any DevTools-related functionality. In [`chrome-extension/manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts), line 72 declares this entry point:

```typescript
devtools_page: 'devtools/index.html',

```

This declaration instructs Chrome to load [`devtools/index.html`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/devtools/index.html) whenever the user opens Chrome DevTools. The HTML file includes a script tag that loads the compiled output from [`pages/devtools/src/index.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools/src/index.ts), establishing the bridge between the extension and Chrome's built-in DevTools.

## Step 2: Creating the Panel via chrome.devtools.panels.create()

The script at [`pages/devtools/src/index.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools/src/index.ts) runs within the DevTools context—not the background script or popup context. It uses the `chrome.devtools.panels` API to register a new panel:

```typescript
// pages/devtools/src/index.ts
try {
  console.log("Edit 'pages/devtools/src/index.ts' and save to reload.");
  // Register a new panel named “Dev Tools” using our custom UI page.
  chrome.devtools.panels.create(
    'Dev Tools',                // Panel title
    '/icon-34.png',            // Optional icon
    '/devtools-panel/index.html' // HTML page rendered inside the panel
  );
} catch (e) {
  console.error(e);
}

```

The `chrome.devtools.panels.create()` method accepts three parameters: the display title for the tab, an optional icon path, and the URL of the HTML page to render within the panel. This call registers the extension's panel as a first-class tab within Chrome's native DevTools interface, alongside Elements, Console, and Network.

## Step 3: Rendering the React UI Inside the Panel

Once Chrome creates the panel, it loads [`/devtools-panel/index.html`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main//devtools-panel/index.html), which bootstraps the React application. The entry point at [`pages/devtools-panel/src/index.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools-panel/src/index.tsx) mounts the component tree:

```tsx
// pages/devtools-panel/src/index.tsx
import '@src/index.css';
import Panel from '@src/Panel';
import { createRoot } from 'react-dom/client';

const init = () => {
  const appContainer = document.querySelector('#app-container');
  if (!appContainer) throw new Error('Can not find #app-container');

  const root = createRoot(appContainer);
  root.render(<Panel />);
};

init();

```

The [`Panel.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/Panel.tsx) component implements the actual UI, utilizing shared utilities for theming and Chrome API access:

```tsx
// pages/devtools-panel/src/Panel.tsx
import '@src/Panel.css';
import { t } from '@extension/i18n';
import { PROJECT_URL_OBJECT, useStorage, withErrorBoundary, withSuspense } from '@extension/shared';
import { exampleThemeStorage } from '@extension/storage';
import { cn, ErrorDisplay, LoadingSpinner } from '@extension/ui';
import type { ComponentPropsWithoutRef } from 'react';

const Panel = () => {
  const { isLight } = useStorage(exampleThemeStorage);
  const logo = isLight ? 'devtools-panel/logo_horizontal.svg' : 'devtools-panel/logo_horizontal_dark.svg';
  const goGithubSite = () => chrome.tabs.create(PROJECT_URL_OBJECT);

  return (
    <div className={cn('App', isLight ? 'bg-slate-50' : 'bg-gray-800')}>
      <header className={cn('App-header', isLight ? 'text-gray-900' : 'text-gray-100')}>
        <button onClick={goGithubSite}>
          <img src={chrome.runtime.getURL(logo)} className="App-logo" alt="logo" />
        </button>
        <p>Edit <code>pages/devtools-panel/src/Panel.tsx</code></p>
        <ToggleButton onClick={exampleThemeStorage.toggle}>{t('toggleTheme')}</ToggleButton>
      </header>
    </div>
  );
};

export default withErrorBoundary(withSuspense(Panel, <LoadingSpinner />), ErrorDisplay);

```

This architecture allows the devtools panel to integrate seamlessly with Chrome's built-in DevTools while maintaining full access to extension APIs like `chrome.runtime.getURL` and `chrome.tabs.create`.

## Communication and Shared Utilities

The integration relies on shared packages to maintain consistency across the extension. The `exampleThemeStorage` utility, defined in the shared packages, synchronizes theme state between the panel and other extension components. The `PROJECT_URL_OBJECT` constant from [`packages/shared/const.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/shared/const.ts) provides standardized URL references.

Error handling and loading states are implemented via higher-order components `withErrorBoundary` and `withSuspense` from `@extension/ui`, ensuring the panel remains stable even when asynchronous operations fail.

## Summary

- **Manifest declaration**: The `devtools_page` entry in [`chrome-extension/manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts) initializes the DevTools integration.
- **Panel registration**: The [`pages/devtools/src/index.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools/src/index.ts) script calls `chrome.devtools.panels.create()` to add a custom tab to Chrome's DevTools.
- **UI rendering**: The [`pages/devtools-panel/src/index.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools-panel/src/index.tsx) entry point mounts a React application inside the panel using standard Chrome extension APIs.
- **Shared architecture**: Utilities from `@extension/shared` and `@extension/ui` provide theming, error handling, and cross-extension communication.

## Frequently Asked Questions

### What is the purpose of the `devtools_page` in the manifest?

The `devtools_page` serves as the entry point that Chrome loads whenever a user opens the browser's DevTools. According to the `chrome-extension-boilerplate-react-vite` source code, this page runs in a special DevTools context and executes the script that calls `chrome.devtools.panels.create()` to register custom panels.

### How does `chrome.devtools.panels.create()` work?

The `chrome.devtools.panels.create()` method registers a new panel tab inside Chrome's native DevTools interface. As implemented in [`pages/devtools/src/index.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools/src/index.ts), it accepts three parameters: the display title for the tab, an optional icon path, and the URL of the HTML page to render within the panel frame.

### Can the DevTools panel communicate with the background script?

Yes, the DevTools panel operates within the extension's context and can access all Chrome extension APIs. The [`Panel.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/Panel.tsx) component demonstrates this by using `chrome.tabs.create()` to open external links and `chrome.runtime.getURL()` to load local assets. It can also use `chrome.runtime.sendMessage()` to communicate with background scripts or other extension components.

### What UI framework does the devtools panel use?

The devtools panel uses React with TypeScript, bundled by Vite. The entry point at [`pages/devtools-panel/src/index.tsx`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/pages/devtools-panel/src/index.tsx) creates a React root and renders the `Panel` component, which utilizes Tailwind CSS for styling and shared packages from `@extension/ui` for error boundaries and suspense handling.