Loading...
Loading...
Browser DevTools extension for debugging HTMX applications with request inspection, element tracking, event timeline, swap visualization, and error detection
npx skill4agent add aradotso/devtools-skills htmx-devtools-extensionSkill by ara.so — Devtools Skills collection.
git clone https://github.com/atoolz/htmx-devtools.git
cd htmx-devtools
npm install
npm run build:chromechrome://extensionsdist/npm run build:firefoxabout:debugging#/runtime/this-firefoxdist/manifest.jsonF12HX-*<!-- This request will appear in the Request Inspector -->
<button hx-get="/api/users"
hx-target="#user-list"
hx-swap="innerHTML">
Load Users
</button>
<div id="user-list"></div>GET/api/users#user-listinnerHTMLHX-Request: trueHX-Target: user-listhx-*<body>
<div hx-boost="true">
<form hx-post="/api/contact" hx-target="#result">
<input name="email" hx-validate="true">
<button type="submit">Submit</button>
</form>
<div id="result" hx-swap-oob="true"></div>
</div>
</body>▼ body
▼ div [hx-boost="true"]
▼ form [hx-post="/api/contact", hx-target="#result"]
• input [hx-validate="true"]
• button
• div#result [hx-swap-oob="true"]htmx:loadhtmx:configRequesthtmx:beforeRequesthtmx:afterRequesthtmx:xhr:loadstarthtmx:xhr:progresshtmx:beforeSwaphtmx:afterSwaphtmx:beforeSwaphtmx:swapErrorhtmx:oobBeforeSwaphtmx:oobAfterSwaphtmx:historyRestorehtmx:pushedIntoHistoryhtmx:beforeTransitionhtmx:afterSettlehtmx:responseErrorhtmx:sendErrorhtmx:targetError// For this htmx request:
// <button hx-get="/data" hx-target="#output">Get Data</button>
// Timeline shows:
// 1. htmx:configRequest (Init) - Request configured
// 2. htmx:beforeRequest (Request) - About to send
// 3. htmx:xhr:loadstart (XHR) - XHR started
// 4. htmx:beforeSwap (Response) - Response received, about to swap
// 5. htmx:afterSwap (Swap) - DOM swapped
// 6. htmx:afterSettle (Transition) - Settling completeevent.detail<!-- Before -->
<div id="content">
<p>Old content</p>
</div>
<!-- Server responds with (hx-swap="innerHTML") -->
<p>New content</p>
<p>Additional paragraph</p>
<!-- After -->
<div id="content">
<p>New content</p>
<p>Additional paragraph</p>
</div><div id="content">
- <p>Old content</p>
+ <p>New content</p>
+ <p>Additional paragraph</p>
</div>hx-target<!-- This will trigger a "Target Not Found" error -->
<button hx-get="/data" hx-target="#missing-element">
Click Me
</button>
<!-- This will trigger an "HTTP Error" if server returns 404 -->
<button hx-get="/nonexistent" hx-target="#output">
Load Missing
</button>Page Script (MAIN world)
↓ postMessage
Content Script (isolated)
↓ chrome.runtime.sendMessage
Service Worker (background)
↓ chrome.runtime.sendMessage
DevTools Panel (Preact UI)src/page-script/index.ts"world": "MAIN"htmx:*src/content-script/index.tswindow.postMessagechrome.runtime.sendMessagesrc/background/index.tssrc/panel/| Feature | htmx 2.x | htmx 4.0 |
|---|---|---|
| Event names | | |
| Request tracking | XHR WeakMap | ctx object WeakMap |
| Detail structure | | |
| Error events | 10 separate events | Unified |
# Development mode with watch
npm run dev
# Production build
npm run build
# Chrome-specific build (copies manifest + icons)
npm run build:chrome
# Firefox-specific build
npm run build:firefox
# TypeScript type checking
npm run typecheckhtmx-devtools/
├── src/
│ ├── page-script/ # Injected into page context
│ ├── content-script/ # Bridge between page and extension
│ ├── background/ # Service worker for state management
│ ├── panel/ # Preact UI components
│ │ ├── components/ # UI components for each tab
│ │ ├── store/ # Signal-based state management
│ │ └── utils/ # Helper functions
│ └── shared/ # Shared types and utilities
├── public/ # Static assets (icons, manifests)
├── test/e2e/fixtures/ # Test server and demo pages
└── dist/ # Build outputnode test/e2e/fixtures/test-server.jshx-trigger="every 2s"test/e2e/fixtures/<!-- test/e2e/fixtures/my-test.html -->
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
</head>
<body>
<button hx-get="/api/test" hx-target="#result">
Test Button
</button>
<div id="result"></div>
</body>
</html>// Check if htmx is properly loaded
console.log(window.htmx); // Should not be undefined
// Verify extension is capturing events
// Open HTMX DevTools tab, click Record button
// Look for "Recording" indicator
// Check if element has valid htmx attributes
const el = document.querySelector('[hx-get]');
console.log(el.getAttribute('hx-get')); // Should show URL<!-- BAD: Target selector is invalid -->
<button hx-get="/data" hx-target="missing">Load</button>
<!-- GOOD: Target exists in DOM -->
<button hx-get="/data" hx-target="#content">Load</button>
<div id="content"></div><div id="parent" hx-boost="true">
<a href="/page1">Link 1</a>
<a href="/page2">Link 2</a>
</div><a>hx-boost<!-- Test different swap strategies -->
<button hx-get="/content" hx-target="#out" hx-swap="innerHTML">innerHTML</button>
<button hx-get="/content" hx-target="#out" hx-swap="outerHTML">outerHTML</button>
<button hx-get="/content" hx-target="#out" hx-swap="beforebegin">beforebegin</button>
<div id="out">Original content</div>// To debug swap issues, enable only Swap category
// Timeline shows: htmx:beforeSwap, htmx:afterSwap, htmx:swapError
// To debug request failures, enable Request + Error categories
// Timeline shows: htmx:beforeRequest, htmx:responseError, etc.
// Search bar filters within visible categories
// Example: Search "error" to find all error-related eventschrome://extensions// 1. Verify htmx is loaded on the page
console.log(window.htmx); // Should output htmx object
// 2. Check if Recording is enabled
// Click the red record button in Request Inspector
// 3. Verify htmx elements are properly configured
document.querySelectorAll('[hx-get], [hx-post], [hx-put], [hx-delete]');
// Should return NodeList with your htmx elements
// 4. Check for JavaScript errors blocking htmx
// Open browser console, look for errors
// 5. Test with simple example
const testBtn = document.createElement('button');
testBtn.setAttribute('hx-get', '/test');
testBtn.textContent = 'Test';
document.body.appendChild(testBtn);
htmx.process(testBtn);
testBtn.click();hx-*htmx:load// 1. Ensure event listeners are not blocked
// Check for errors in background service worker
// 2. Verify htmx events are firing
document.addEventListener('htmx:afterRequest', (e) => {
console.log('Request completed:', e.detail);
});
// 3. Check category filters in Timeline tab
// Ensure at least one category is enabled
// 4. Clear and re-record
// Click Clear button, then trigger a new htmx request// Check actual htmx version
console.log(htmx.version);
// htmx 2.x: Returns string like "2.0.0"
// htmx 4.0: Returns string like "4.0.0-alpha1"
// Reload extension and page if version changed
// Extension detects version on page load# Pull latest changes
git pull origin main
# Rebuild extension
npm install
npm run build:chrome # or build:firefox
# Reload extension
# 1. Go to chrome://extensions
# 2. Click reload icon on htmx-devtools extension
# 3. Refresh pages with htmx