👨🏼‍💻

khriztianmoreno's Blog

Home Tags About |

Posts with tag chrome-devtools

AI-Powered Web Debugging - From Browser Runtime to Autonomous Agent

2026-05-18
debuggingmcpchrome-devtoolsaiperformance

For years, AI-powered web debugging had a fundamental problem: models were programming blindfolded. They could read your source code, but they couldn't see what was happening in the browser when that code was executing. They couldn't see the memory leak, the failed network request, or the layout shift that only occurs under specific conditions.That changed with the arrival of the Model Context Protocol (MCP) and the Chrome DevTools MCP Server — an official Google server that directly connects AI agents to the browser's rendering engine. The agent no longer theorizes about your code: it observes it running in real-time and acts on it.1. The Problem: The Blindness of Static CodeA traditional LLM analyzes source code as static text. It can detect syntax errors, suggest refactors, and explain logic. But when the question is "why is my LCP at 4.2 seconds on mobile?" or "why does the cart fail only when the user comes from a payment redirect?", the model has no real data to answer.The Chrome DevTools Protocol (CDP) has been the foundation of tools like Puppeteer and Playwright for years. The Chrome DevTools MCP Server exposes it directly to any MCP-compatible agent.2. Setup: Connecting the Agent to the BrowserInstallationThe official package is published on npm as chrome-devtools-mcp:# Run directly without installing (recommended for testing) npx -y chrome-devtools-mcp@latest # Or install globally npm install -g chrome-devtools-mcpIDE ConfigurationFor Cursor or VS Code with MCP extension, create or edit .cursor/mcp.json (or .vscode/mcp.json):{ "mcpServers": { "chrome-devtools": { "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"] } } }For Claude Code (CLI), the file is ~/.claude/claude_desktop_config.json:{ "mcpServers": { "chrome-devtools": { "command": "npx", "args": ["-y", "chrome-devtools-mcp@latest"] } } }Two Connection ModesIsolated Mode (recommended): The server launches a clean Chrome instance with a temporary profile. The agent has full control without touching your main session.--autoConnect Mode (Chrome M144+): Connects directly to your active session. To enable it, open chrome://inspect/#remote-debugging and accept the permission dialog when the agent attempts to connect.# Connect to an active Chrome session npx -y chrome-devtools-mcp@latest --autoConnectWarning: With --autoConnect the agent can read cookies and active sessions. Use it only in development profiles, never in your personal profile.3. Available ToolsThe server exposes 45 tools divided into categories. The most useful ones for day-to-day work:| Category | Key Tools | |---|---| | Automation | click, fill_form, type_text, drag, hover | | Navigation | navigate_page, wait_for, list_pages | | Performance | performance_start_trace, performance_stop_trace, performance_analyze_insight | | Network | get_network_request, list_network_requests | | Inspection | evaluate_script, list_console_messages, take_screenshot | | Memory | take_heapsnapshot, get_heapsnapshot_summary | | Emulation | emulate, resize_page |4. Real-World Use CasesA. Core Web Vitals AuditingThe agent can simulate degraded network conditions and analyze metrics like LCP (Largest Contentful Paint) and INP (Interaction to Next Paint) using real browser data, not estimates.Example Prompt:Navigate to http://localhost:3000, emulate a Slow 3G connection, start a performance trace, reload the page, stop the trace and tell me what is blocking the LCP.What the agent runs internally:await navigate_page({ url: "http://localhost:3000" }); await emulate({ network: "slow3G" }); await performance_start_trace(); await navigate_page({ url: "http://localhost:3000" }); await performance_stop_trace(); const insight = await performance_analyze_insight();If it detects a hero image with loading="lazy" blocking the LCP, it proposes a direct fix:// Before — the browser delays loading this image <Image src="/hero.webp" alt="Hero" loading="lazy" /> // After — preloaded as a critical resource <Image src="/hero.webp" alt="Hero" priority />B. Persisting Inspector Changes to Source CodeYou adjust margins in the Chrome inspector, refresh, and the change disappears. With the connected agent, you make the visual adjustment in the browser and then ask:I just changed the padding of the Card component in the inspector. Extract the current styles from the DOM and update the stylesheet file.The agent runs:// Extracts computed styles from the modified element const styles = await evaluate_script({ expression: ` const el = document.querySelector('.card'); const computed = window.getComputedStyle(el); return { padding: computed.padding, borderRadius: computed.borderRadius, boxShadow: computed.boxShadow }; ` }); // Then locates the corresponding stylesheet file and applies the diffC. Automated QA and Silent Error DetectionErrors that only happen under specific interactions — OAuth flows, carts with combined discounts, multi-step forms — are the most expensive to find. The agent can run the full flow and monitor the console and network in parallel:Complete the checkout flow: add product 42 to the cart, apply the PROMO10 coupon, pay with the test card 4242 4242 4242 4242, and report any console or network errors.await navigate_page({ url: "http://localhost:3000/product/42" }); await click({ selector: "#add-to-cart" }); await navigate_page({ url: "http://localhost:3000/cart" }); await fill_form({ selector: "#coupon-input", value: "PROMO10" }); await click({ selector: "#checkout-btn" }); // Capture network errors during the whole flow const requests = await list_network_requests(); const failedRequests = requests.filter(r => r.status >= 400); // Capture console errors const logs = await list_console_messages(); const errors = logs.filter(log => log.type === "error");If an endpoint responds with HTTP 500, the agent captures the stack trace through source maps, correlates it with the source code, and proposes a fix.D. Memory Leak DetectionMemory leaks in SPAs are hard to diagnose manually. The agent can compare heap snapshots before and after a navigation sequence:Navigate between /dashboard and /reports 10 times and tell me if there is a memory leak.// Initial snapshot await take_heapsnapshot(); const before = await get_heapsnapshot_summary(); // Simulate repeated navigation for (let i = 0; i < 10; i++) { await navigate_page({ url: "http://localhost:3000/dashboard" }); await navigate_page({ url: "http://localhost:3000/reports" }); } // Final snapshot and comparison await take_heapsnapshot(); const after = await get_heapsnapshot_summary(); // The agent compares retainers and reports unreleased objects5. Security: What You Can't IgnoreMandatory Profile Isolation. If the agent has simultaneous access to your terminal and your personal browser, a prompt injection attack from a malicious site could read session cookies, auth tokens, or extract info from forms with saved credentials. Always use a dedicated Chrome profile for development:# Create and use an isolated Chrome profile google-chrome --user-data-dir=/tmp/dev-profile --no-first-runAvoid Context Contamination. Don't add all available MCP servers to your workspace. Each additional server consumes model context tokens and degrades the precision of its decisions. Configure only the relevant servers for the current task — a frontend debugging workspace doesn't need the database or GitHub MCP at the same time.ConclusionWeb debugging has evolved from a manual inspection process to an automated, continuous workflow of agent-based observability. By equipping language models with the ability to interact directly with the rendering engine and Chrome’s internal tools, we bridge the gap between design intent and real-world execution. Developers who adopt this interactive workflow will not only drastically reduce the time spent hunting down repetitive bugs, but will also raise the standard of optimization and reliability of their applications to unprecedented levelsProfile@khriztianmoreno �

Mastering Chrome DevTools for Web Performance Optimization

2025-11-17
performancedevtoolschromechrome-devtools

Turn Chrome DevTools from a viewer into a performance debugging weapon.Most teams open DevTools too late. Or they look at the wrong panels, drowning in noise while missing the signals that actually affect user experience.If you are a senior frontend engineer or performance owner, you know that "it feels slow" isn't a bug report—it's a symptom. This guide is for those who need to diagnose that symptom, understand the root cause, and verify the fix.We are focusing on Chrome DevTools features that directly map to Core Web Vitals. No fluff, just the workflows you need to fix Interaction to Next Paint (INP), Largest Contentful Paint (LCP), and Cumulative Layout Shift (CLS).1. Mental model: from symptom to root causeBefore clicking anything, you need the right mental model. Metrics tell you what is wrong. DevTools explains why.Performance isn't about magic numbers; it's about the Main Thread. The browser's main thread is where JavaScript runs, HTML is parsed, and styles are calculated. It is a single-lane highway. If a heavy truck (a long task) is blocking the lane, fast cars (user clicks, animations) are stuck in traffic.Key Rule: If the main thread is blocked, UX is broken.2. Performance panel: the center of truthThe Performance panel allows you to record exactly what the browser is doing over a period of time. It records:Main thread activity: JS execution, parsing, GC.Rendering pipeline: Style calc, Layout, Paint, Compositing.Network timing: When resources are requested and received relative to execution.User input handling: How long the browser took to respond to a click.Recording a useful traceIdle traces are useless. You need interaction traces.Open DevTools (Cmd+Option+I / Ctrl+Shift+I) and go to the Performance tab.Check Screenshots and Web Vitals in the capture settings. Memory is usually optional unless you suspect a leak.Click the Record button (circle icon).Interact with the page (click the button, scroll the list, open the modal).Click Stop.3. Reading the Performance timelineThe resulting trace can be intimidating. Ignore 90% of it initially. Focus on these sections: FPS & CPU: High-level health check. Solid blocks of color in CPU mean the main thread is busy.Network: Thin lines showing resource loading order.Main: The flame chart of call stacks. This is where you spend most of your time. Frames: Screenshots of what the user saw at that millisecond.The Experience TrackThis is your best friend. It explicitly marks:LCP: Where the Largest Contentful Paint occurred.Layout Shifts: Red diamonds indicating CLS.Long Tasks: Tasks taking >50ms (red triangles).Spotting Long TasksA "Long Task" is any task that keeps the main thread busy for more than 50ms. In the Main section, look for gray bars with red triangles at the top corner. These are the tasks blocking the browser from responding to user input (INP).4. Debugging LCP with DevToolsLCP measures loading performance. To fix it, you need to know what the element is and why it was late.Identify the LCP element: In the Timings or Experience track, find the LCP marker.Inspect the element: Hovering over the LCP marker often highlights the actual DOM node.Analyze the delay:Resource Load Delay: Was the image discovery late? (e.g., lazy-loaded hero image).Resource Load Duration: Was the network slow or the image too large?Render Delay: Was the image loaded but waiting for a main-thread task to finish before painting?Typical LCP root causes:Late discovery: The <img> tag is generated by JavaScript or has loading="lazy".Render blocking: Huge CSS bundles or synchronous JS in the <head> pausing the parser.Server TTFB: The backend took too long to send the initial HTML.<!-- ❌ Bad: Lazy loading the LCP element (e.g. Hero image) --> <img src="hero.jpg" loading="lazy" alt="Hero Image" /> <!-- ✅ Good: Eager loading + fetchpriority --> <img src="hero.jpg" loading="eager" fetchpriority="high" alt="Hero Image" />Reference: Optimize Largest Contentful Paint5. Debugging INP with DevToolsINP is the metric that kills single-page applications (SPAs). It measures the latency of user interactions.Use the Interactions track: Look for the specific interaction (click, keypress) you recorded.Expand the Interaction: You will see it broken down into three phases:Input Delay: Time waiting for the main thread to become free.Processing Time: Time running your event handlers.Presentation Delay: Time waiting for the browser to paint the next frame.Visually correlate with the Main Thread: Click the interaction bar. Look directly below it in the Main track.If you see a massive yellow block of JavaScript under the interaction, your event handler is too slow (Processing Time).If you see a massive block of JS before the interaction starts, the main thread was busy doing something else (Input Delay).Common offenders:JSON parsing large payloads.React/Vue reconciliation (rendering too many components).Synchronous loops or expensive calculations.// ❌ Bad: Blocking the main thread with heavy work button.addEventListener("click", () => { const result = heavyCalculation(); // Blocks for 200ms updateUI(result); }); // ✅ Good: Yielding to main thread button.addEventListener("click", async () => { showSpinner(); // Yield to main thread so browser can paint the spinner await new Promise((resolve) => setTimeout(resolve, 0)); const result = heavyCalculation(); updateUI(result); });Fix workflow: Identify the function in the flame chart → Optimize or defer it → Record again → Verify the block is smaller.Reference: Interaction to Next Paint (INP)6. Debugging CLS with DevToolsLayout shifts are annoying and confusing. DevTools visualizes them clearly.Open the Command Menu (Cmd+Shift+P / Ctrl+Shift+P) and type "Rendering".Enable "Layout Shift Regions".As you interact with the page, shifted elements will flash blue.In the Performance Trace: Look at the Experience track for red diamonds. Click one. The Summary tab at the bottom will list exactly which nodes moved and their previous/current coordinates.Common CLS patterns:Font swaps (FOUT/FOIT): Text renders, then the web font loads, changing the size.Image resize: Images without width and height attributes.Late injected UI: Banners or ads inserting themselves at the top of the content./* ❌ Bad: No space reserved for image */ img.hero { width: 100%; height: auto; } /* ✅ Good: Reserve space with aspect-ratio */ img.hero { width: 100%; height: auto; aspect-ratio: 16 / 9; }Reference: Optimize Cumulative Layout Shift7. Live Metrics screenThe Live Metrics view (in the Performance panel sidebar or landing page) provides real-time feedback without a full trace.Why it matters:Instant feedback: See LCP and CLS values update as you resize the window or navigate.Field-aligned: It uses the same implementation as the Web Vitals extension.Use cases:Testing hover states and small interactions.Validating SPA route transitions.Quick sanity checks before committing code.Note: This is still "Lab Data" running on your machine, not real user data (CrUX).8. Insights panelThe Performance Insights panel is an experimental but powerful automated analysis layer. It uses the trace data to highlight risks automatically.Key features:Layout Shift Culprits: It points directly to the animation or DOM update that caused a shift.Render blocking requests: identifies CSS/JS that delayed the First Contentful Paint.Long main-thread tasks: suggestions on how to break them up.Use Insights as a hint, not a verdict. It points you to the right place in the flame chart, but you still need to interpret the code.9. CPU and Network throttling (Mandatory)Developing on a MacBook Pro with fiber internet is a lie. Your users are on mid-tier Android devices with spotty 4G.CPU Throttling:set to 4x slowdown. This roughly simulates a mid-range Android device. It exposes "death by a thousand cuts"—small scripts that feel instant on desktop but freeze a phone for 300ms.Network Throttling: Fast 4G or Slow 4G. Critical for debugging LCP (image load times) and font loading behavior.Fast Wi-Fi hides bad engineering. Always throttle when testing performance.10. Putting it all together: a repeatable workflowDetect: Use PageSpeed Insights or CrUX to identify which metric is failing.Reproduce: Open DevTools, enable Throttling (CPU 4x, Network 4G).Record: Start tracing, perform the user action, stop tracing.Inspect: Find the red/yellow markers in the Experience/Main tracks.Fix: Apply the code change (defer JS, optimize images, reduce DOM depth).Verify: Re-record and compare the trace. Did the long task disappear? Did the LCP marker move left?ConclusionDevTools is not optional. Performance is observable. Every Core Web Vitals issue leaves a trace; you just need to know where to look.If you cannot explain a performance problem in DevTools, you do not understand it yet.Resources:Chrome DevTools Documentationweb.dev Performance GuidesGoogle Search Central CWV DocsI hope this has been helpful and/or taught you something new!Profile@khriztianmorenoUntil next time

Optimizing for Speed - Practical Strategies to Improve Your Core Web Vitals

2025-11-04
performancecore-web-vitalsweb-vitalslcpinpclschrome-devtools

Pages can load fast.And still feel slow.That’s the modern performance trap: you ship a “snappy” initial render, but interactions hitch, UI jumps, and the page loses trust. Core Web Vitals are designed to catch that gap—and they’re judged in the field, not in your local Lighthouse run.

Demystifying Core Web Vitals - A Developer's Guide to LCP, INP, and CLS

2025-10-19
web-performancecore-web-vitalslighthouseweb-developmentcruxchromeperformancedevtoolschrome-devtools

Core Web Vitals are ranking signals, but most teams still optimize them like lab-only scorecards. This guide turns CWV into actionable engineering work: how to measure (field + lab), how to debug root causes in DevTools, and which fixes actually move the 75th percentile.

Introducing Chrome DevTools MCP

2025-09-30
javascriptchromedevtoolsaimcpdebuggingperformancechrome-devtools

I participated in the Chrome DevTools MCP Early Access Program and put the feature through its paces on real projects. I focused on four scenarios: fixing a styling issue, running performance traces and extracting insights, debugging a failing network request, and validating optimal caching headers for assets. This post shares that hands-on experience—what worked, where it shines, and how I’d use it day-to-day.Chrome DevTools MCP gives AI coding assistants actual visibility into a live Chrome browser so they can inspect, test, measure, and fix issues based on real signals—not guesses. In practice, this means your agent can open pages, click, read the DOM, collect performance traces, analyze network requests, and iterate on fixes in a closed loop.