Build a Chrome DevTools Panel Extension

16 min read

Build a Chrome DevTools Panel Extension

Build a Chrome DevTools Panel Extension

Chrome DevTools is the most powerful browser-based debugging environment available today. Built directly into Google Chrome, it provides developers with deep insights into webpage performance, network activity, DOM structure, and application state. But what if you could extend DevTools with your own custom panels? Imagine having a specialized tool that integrates directly into the Chrome development workflow, giving you custom analytics, debugging capabilities, or visualization tools right alongside Elements, Console, and Network tabs.

This comprehensive guide will walk you through building a complete Chrome DevTools Panel Extension from scratch. Whether you want to create a custom debugging tool, visualize application data, or build a specialized inspector for your framework, this tutorial covers everything you need to know about the devtools panel architecture in Manifest V3.


Understanding Chrome DevTools Extensions

Chrome DevTools extensions come in several flavors, each serving different purposes within the development workflow. Before diving into panel development, it is essential to understand the different types of DevTools extensions available.

Types of DevTools Extensions

The Chrome DevTools extension ecosystem offers three primary extension points that you can leverage to enhance the development experience:

DevTools Pages are the most visible type of DevTools extension. These are custom panels that appear as new tabs within Chrome DevTools, alongside built-in tabs like Elements, Console, Network, and Sources. When you create a devtools page, it becomes an integral part of the DevTools interface, giving users direct access to your custom tooling.

DevTools Panels are specifically the UI components that users interact with inside DevTools. A devtools page can contain one or more panels, each representing a distinct functionality. For example, you might have a panel for viewing application state, another for analyzing performance metrics, and a third for debugging specific features.

DevTools Insets are smaller UI elements that can be embedded within existing DevTools tabs. These are less common but useful for adding contextual tools to existing panels without creating entirely new tabs.

The distinction between devtools pages and devtools panels is subtle but important: the page is the container, while the panel is the interactive interface users see. For most use cases, you will create a devtools page with a single custom panel.

How DevTools Extensions Communicate

A crucial aspect of building DevTools extensions is understanding how your custom panels communicate with the inspected page. This communication happens through a specialized API that establishes a connection between the DevTools context and the webpage context.

The chrome.devtools.inspectedWindow API provides the bridge between your panel and the page being inspected. You can evaluate JavaScript in the context of the inspected page, access the DOM, listen for console messages, and even reload the page with different configurations. This bidirectional communication is the foundation for building powerful debugging and analysis tools.

Additionally, you can use the standard Chrome message passing system to communicate between your DevTools panel and other extension components like background scripts or popup pages. This allows you to build complex extensions that coordinate functionality across multiple parts of the Chrome extension architecture.


Project Setup and Manifest Configuration

Every Chrome extension begins with the manifest file, and DevTools extensions are no exception. Let us set up a proper Manifest V3 configuration for our DevTools panel extension.

Creating the Manifest

Create a new directory for your project and add the following manifest.json file:

{
  "manifest_version": 3,
  "name": "Custom DevTools Panel",
  "version": "1.0",
  "description": "A custom DevTools panel for advanced debugging and analysis",
  "devtools_page": "devtools.html",
  "permissions": [
    "devtools_page"
  ]
}

The critical difference here is the devtools_page key instead of the standard background or content_scripts you might see in other extensions. This tells Chrome to load your custom DevTools page when the DevTools are opened.

Creating the DevTools Page

Create a devtools.html file that will serve as the entry point for your DevTools extension:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>
<body>
  <script src="devtools.js"></script>
</body>
</html>

This simple HTML file loads your main JavaScript file, which will create and configure your custom panel. The devtools.js file is where the magic happens, as we will explore in the next section.


Creating Your First DevTools Panel

Now comes the exciting part: creating your custom panel. The chrome.devtools.panels API is your gateway to adding new functionality to Chrome DevTools.

The Panel Creation Process

Open your devtools.js file and add the following code to create your first panel:

// Create a new panel with title, icon, and callback
chrome.devtools.panels.create(
  "My Custom Panel",           // Panel title
  "icon.png",                  // Icon (optional)
  "panel.html",                // Panel HTML file
  function(panel) {
    // Panel callback - panel is created but not yet visible
    console.log("Custom panel created!");
    
    // You can set up event listeners here
    panel.onShown.addListener(function(panelWindow) {
      console.log("Panel is now visible!");
    });
    
    panel.onHidden.addListener(function() {
      console.log("Panel is hidden!");
    });
  }
);

This code creates a new panel titled “My Custom Panel” that appears as a new tab in Chrome DevTools. When clicked, it loads the content from panel.html. The callback function gives you access to the panel object, which you can use to listen for visibility changes and perform additional setup.

Building the Panel UI

Create a panel.html file with a functional UI:

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      padding: 16px;
      margin: 0;
      background: #f5f5f5;
    }
    
    .header {
      background: #24292e;
      color: white;
      padding: 12px 16px;
      margin: -16px -16px 16px -16px;
      font-weight: 600;
    }
    
    .info-box {
      background: white;
      border: 1px solid #ddd;
      border-radius: 6px;
      padding: 16px;
      margin-bottom: 12px;
    }
    
    .button {
      background: #0366d6;
      color: white;
      border: none;
      padding: 8px 16px;
      border-radius: 6px;
      cursor: pointer;
      font-size: 14px;
    }
    
    .button:hover {
      background: #0256b9;
    }
    
    #output {
      background: #1e1e1e;
      color: #d4d4d4;
      padding: 12px;
      border-radius: 6px;
      font-family: 'Monaco', 'Menlo', monospace;
      font-size: 12px;
      min-height: 200px;
      white-space: pre-wrap;
    }
  </style>
</head>
<body>
  <div class="header">DevTools Panel Extension</div>
  
  <div class="info-box">
    <h3>Page Information</h3>
    <p>Current URL: <span id="url">Loading...</span></p>
    <p>Title: <span id="title">Loading...</span></p>
  </div>
  
  <div class="info-box">
    <button id="refreshBtn" class="button">Refresh Data</button>
    <button id="evaluateBtn" class="button">Run Test Script</button>
  </div>
  
  <div id="output">Output will appear here...</div>
  
  <script src="panel.js"></script>
</body>
</html>

This creates a clean, functional UI with page information display, action buttons, and an output area. The styling follows Chrome DevTools conventions to ensure visual consistency.


Connecting to the Inspected Window

The real power of DevTools panels comes from their ability to interact with the page being inspected. Let us add the functionality to retrieve page information and execute scripts in the page context.

Accessing Page Information

Create a panel.js file with the following code to connect to the inspected window:

// Get reference to UI elements
const urlElement = document.getElementById('url');
const titleElement = document.getElementById('title');
const outputElement = document.getElementById('output');
const refreshBtn = document.getElementById('refreshBtn');
const evaluateBtn = document.getElementById('evaluateBtn');

// Function to update page information
function updatePageInfo() {
  // Use inspectedWindow to evaluate script in page context
  chrome.devtools.inspectedWindow.eval(
    "window.location.href",
    function(result, isException) {
      if (!isException) {
        urlElement.textContent = result;
      } else {
        urlElement.textContent = "Error: " + isException.value;
      }
    }
  );
  
  chrome.devtools.inspectedWindow.eval(
    "document.title",
    function(result, isException) {
      if (!isException) {
        titleElement.textContent = result;
      } else {
        titleElement.textContent = "Error: " + isException.value;
      }
    }
  );
}

// Function to evaluate custom scripts
function runTestScript() {
  chrome.devtools.inspectedWindow.eval(
    `(function() {
      // Create a sample result object
      return {
        timestamp: new Date().toISOString(),
        userAgent: navigator.userAgent,
        screenWidth: screen.width,
        screenHeight: screen.height,
        memory: performance.memory ? {
          totalJSHeapSize: performance.memory.totalJSHeapSize,
          usedJSHeapSize: performance.memory.usedJSHeapSize
        } : 'Not available',
        elements: document.querySelectorAll('*').length
      };
    })()`,
    function(result, isException) {
      if (!isException) {
        outputElement.textContent = JSON.stringify(result, null, 2);
      } else {
        outputElement.textContent = "Error: " + isException.value;
      }
    }
  );
}

// Set up event listeners
refreshBtn.addEventListener('click', updatePageInfo);
evaluateBtn.addEventListener('click', runTestScript);

// Initial load
updatePageInfo();

// Listen for page reloads
chrome.devtools.inspectedWindow.onResourceContentAdded.addListener(function(resource) {
  outputElement.textContent += '\nPage resource changed: ' + resource.url;
});

This code demonstrates several key capabilities of the DevTools API. The chrome.devtools.inspectedWindow.eval() method allows you to execute JavaScript in the context of the inspected page, giving you access to the DOM, window objects, and page-specific data. The callback pattern follows Chrome’s standard async approach, returning both the result and any exceptions.


Advanced Features and Best Practices

Now that you have a working panel, let us explore advanced features that will make your DevTools extension truly professional.

Adding Panel-to-Background Communication

For more complex extensions, you might need to communicate between your panel and background scripts. Here is how to set up message passing:

// In panel.js - sending messages to background
chrome.runtime.sendMessage(
  { from: 'panel', action: 'getData' },
  function(response) {
    console.log('Response from background:', response);
  }
);

// Receiving messages from background
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  if (message.from === 'background') {
    outputElement.textContent = 'Received: ' + JSON.stringify(message.data);
  }
});

Adding Custom Sidebars

DevTools panels can include sidebars that provide additional context or navigation. Here is how to add a sidebar to your panel:

chrome.devtools.panels.create(
  "Custom Panel",
  "icon.png",
  "panel.html",
  function(panel) {
    panel.onShown.addListener(function(panelWindow) {
      // Create a sidebar
      var sidebarPane = panelWindow.chrome.devtools.panels.createSidebarPane(
        "Element Tree",
        function(sidebar) {
          sidebar.setPage("sidebar.html");
        }
      );
    });
  }
);

Theme Support

Professional DevTools extensions should respect the user’s chosen theme. Chrome DevTools supports both light and dark themes, and your panels should adapt accordingly:

// Detect current theme
chrome.devtools.panels.themeName.onChanged.addListener(function(theme) {
  if (theme === 'dark') {
    document.body.classList.add('dark-theme');
    document.body.classList.remove('light-theme');
  } else {
    document.body.classList.add('light-theme');
    document.body.classList.remove('dark-theme');
  }
});

// Get initial theme
chrome.devtools.panels.themeName.get(function(theme) {
  if (theme === 'dark') {
    document.body.classList.add('dark-theme');
  } else {
    document.body.classList.add('light-theme');
  }
});

Performance Considerations

When building DevTools panels that interact with the inspected page, performance is crucial. Here are some best practices to ensure your extension remains responsive:

Debounce frequent operations: If you are listening to events that fire rapidly (like scroll or mouse movements), debounce your handlers to prevent overwhelming the page or your panel.

Use Web Workers for heavy computation: Keep your panel responsive by moving intensive processing to Web Workers rather than blocking the main thread.

Limit DOM queries: When inspecting the page, cache DOM references rather than repeatedly querying the same elements.

Throttle communication: If you need to send frequent updates between the panel and the page, batch your updates and send them at a controlled rate.


Testing and Debugging Your Extension

Development and debugging of DevTools extensions requires a different approach than regular Chrome extensions.

Loading Your Extension

To test your DevTools extension:

  1. Open Chrome and navigate to chrome://extensions
  2. Enable “Developer mode” in the top right corner
  3. Click “Load unpacked” and select your extension directory
  4. Open DevTools (F12 or right-click > Inspect)
  5. Look for your custom panel in the DevTools tabs

Debugging Techniques

Use the console within your panel to debug just like regular web development. Additionally, you can access the DevTools debugging API:

// Log to the main DevTools console
chrome.devtools.inspectedWindow.eval("console.log('Message from panel')");

// Or use the panel's own console
console.log("Debug from panel");

Common Issues and Solutions

Several common issues arise when building DevTools extensions. Here are solutions to problems you might encounter:

Panel not appearing: Ensure your manifest.json correctly references the devtools_page and that all file paths are correct. Check chrome://extensions for any error messages.

Communication failures: Remember that the inspected window context is separate from your panel context. Always use chrome.devtools.inspectedWindow.eval() for page interaction.

Script injection errors: The inspected window has a Content Security Policy that may prevent certain script executions. Test thoroughly with real pages and handle exceptions gracefully.


Real-World Applications

Chrome DevTools panel extensions have numerous practical applications. Here are some examples of what you can build:

Framework Debuggers: React, Vue, and Angular DevTools are all implemented as DevTools panel extensions. They provide component trees, state inspection, and performance profiling specific to each framework.

API Debugging Tools: Custom panels can visualize API responses, test endpoints, and manage environment variables directly within DevTools.

Performance Profilers: Build specialized profiling tools that track specific metrics relevant to your application, beyond what Chrome’s built-in profiler offers.

Design System Inspectors: Create tools that help developers understand and navigate design system components, showing props, variants, and usage examples.

Memory Leak Detectors: Implement custom heap analysis tools that track object creation and retention over time.


Publishing Your Extension

Once your DevTools panel extension is ready, you can publish it to the Chrome Web Store. The process is similar to publishing regular extensions:

  1. Package your extension using chrome://extensions > Pack extension
  2. Create a developer account at the Chrome Web Store
  3. Upload your packaged extension
  4. Add screenshots, descriptions, and categories
  5. Submit for review

When describing your extension in the store listing, emphasize that it adds a custom panel to Chrome DevTools, as this is a unique capability that differentiates your extension from regular browser extensions.


Conclusion

Building a Chrome DevTools Panel Extension opens up incredible possibilities for enhancing the development workflow. Whether you are creating a debugging tool for your team, a framework inspector, or a specialized analysis tool, the DevTools extension platform provides a powerful foundation.

In this guide, you learned how to set up a Manifest V3 extension with devtools_page, create custom panels using the chrome.devtools.panels API, communicate with the inspected page using chrome.devtools.inspectedWindow, and implement advanced features like theme support and background script integration.

The techniques covered here form the basis for building professional-grade DevTools extensions. As you continue developing, explore the full Chrome DevTools APIs, experiment with different panel layouts, and consider how your extension can integrate seamlessly with the existing DevTools workflow.

Start building your custom DevTools panel today and transform how you debug and analyze web applications!


Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.

No previous article
No next article