<?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: Arunmozhi Varman</title>
    <description>The latest articles on DEV Community by Arunmozhi Varman (@arunmozhi_varman_k).</description>
    <link>https://dev.to/arunmozhi_varman_k</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2705354%2F9ac8a78e-3501-4922-9eda-cbc3c3b4665f.png</url>
      <title>DEV Community: Arunmozhi Varman</title>
      <link>https://dev.to/arunmozhi_varman_k</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arunmozhi_varman_k"/>
    <language>en</language>
    <item>
      <title>Building a Local, GPU-Accelerated Background Remover MCP Server in Python</title>
      <dc:creator>Arunmozhi Varman</dc:creator>
      <pubDate>Fri, 05 Jun 2026 06:24:28 +0000</pubDate>
      <link>https://dev.to/arunmozhi_varman_k/building-a-local-gpu-accelerated-background-remover-mcp-server-in-python-53hk</link>
      <guid>https://dev.to/arunmozhi_varman_k/building-a-local-gpu-accelerated-background-remover-mcp-server-in-python-53hk</guid>
      <description>&lt;p&gt;I have drafted a blog post highlighting your newly published project: &lt;strong&gt;&lt;code&gt;bg-vanish-mcp&lt;/code&gt;&lt;/strong&gt;. It covers the motivation, tech stack (DirectML + U2NET), implementation details, and how to use it.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building a Local, GPU-Accelerated Background Remover MCP Server in Python
&lt;/h1&gt;

&lt;p&gt;As AI assistants like Claude and Windsurf become more integrated into our daily workflows, equipping them with local capabilities (via the &lt;strong&gt;Model Context Protocol&lt;/strong&gt; or &lt;strong&gt;MCP&lt;/strong&gt;) changes the game. &lt;/p&gt;

&lt;p&gt;Today, we are announcing &lt;strong&gt;&lt;code&gt;bg-vanish-mcp&lt;/code&gt;&lt;/strong&gt;—a local-first, GPU-accelerated background removal MCP server that allows your AI assistants to isolate subjects from images instantly, completely offline, and free of charge.&lt;/p&gt;

&lt;p&gt;Here is a look at why we built it, how it works, and how you can run it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Local-First &amp;amp; GPU-Accelerated?
&lt;/h2&gt;

&lt;p&gt;While cloud-based background removal APIs exist, they come with caveats:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: Pay-per-image structures quickly add up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;: Uploading sensitive images to third-party servers isn't always ideal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed &amp;amp; Latency&lt;/strong&gt;: Sending high-resolution images back and forth over the network is slow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;bg-vanish-mcp&lt;/code&gt;&lt;/strong&gt; solves this by running U2NET models locally using the &lt;code&gt;rembg&lt;/code&gt; library. To keep processing times under a second, it leverages &lt;strong&gt;DirectML&lt;/strong&gt; via ONNX Runtime, allowing hardware acceleration across NVIDIA, AMD, and Intel GPUs natively on Windows—no CUDA or complex SDK configuration required.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works: The Tools
&lt;/h2&gt;

&lt;p&gt;The MCP server exposes two core tools to the AI assistant:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;remove_background(input_path, output_path, return_base64)&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Operates directly on the host file system. The AI passes a local image path, and the server output saves a clean, transparent PNG in the same directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;remove_background_base64(image_base64)&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Allows direct data passing. The AI can send base64-encoded image data in-context, receive the isolated subject as a base64 string, and render it directly in the chat interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Under the Hood: The Code
&lt;/h2&gt;

&lt;p&gt;The server is implemented in Python using the official &lt;strong&gt;FastMCP&lt;/strong&gt; SDK. The core execution provider setup selectively activates the GPU:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rembg&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.server.fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;

&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bg-vanish-mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Read target environment configuration
&lt;/span&gt;&lt;span class="n"&gt;use_gpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USE_GPU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;use_gpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Try GPU acceleration via CUDA or DirectML, fallback to CPU
&lt;/span&gt;    &lt;span class="n"&gt;providers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CUDAExecutionProvider&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DmlExecutionProvider&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CPUExecutionProvider&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;providers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CPUExecutionProvider&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize the ONNX session
&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rembg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By requesting the &lt;code&gt;DmlExecutionProvider&lt;/code&gt; (DirectML) before falling back to CPU, the server gains access to native DirectX 12 hardware acceleration on Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started in Seconds
&lt;/h2&gt;

&lt;p&gt;We have published &lt;strong&gt;&lt;code&gt;bg-vanish-mcp&lt;/code&gt;&lt;/strong&gt; to PyPI so you can run it instantly without configuring local Python environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install &amp;amp; Run via &lt;code&gt;uvx&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Make sure you have &lt;a href="https://github.com/astral-sh/uv" rel="noopener noreferrer"&gt;uv&lt;/a&gt; installed, then add this block to your Claude Desktop configuration (&lt;code&gt;%APPDATA%\Claude\claude_desktop_config.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bg-vanish-mcp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bg-vanish-mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"USE_GPU"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Run Locally with Pip
&lt;/h3&gt;

&lt;p&gt;If you prefer standard pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"bg-vanish-mcp[dml]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And point your MCP client to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bg-vanish-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first run, the server will download the U2NET ONNX model automatically, bind to your GPU, and be ready to start removing backgrounds in milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Out the Code
&lt;/h2&gt;

&lt;p&gt;The project is fully open source. Check out the repository, submit issues, or contribute new features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/AMV0027/bg-vanish-mcp" rel="noopener noreferrer"&gt;https://github.com/AMV0027/bg-vanish-mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyPI&lt;/strong&gt;: &lt;a href="https://pypi.org/project/bg-vanish-mcp/" rel="noopener noreferrer"&gt;https://pypi.org/project/bg-vanish-mcp/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>machinelearning</category>
      <category>mcp</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How I Built Pop-Upz: An Always-on-Top Floating Web Player Using Chrome's Document PiP API</title>
      <dc:creator>Arunmozhi Varman</dc:creator>
      <pubDate>Thu, 04 Jun 2026 18:31:44 +0000</pubDate>
      <link>https://dev.to/arunmozhi_varman_k/how-i-built-pop-upz-an-always-on-top-floating-web-player-using-chromes-document-pip-api-5544</link>
      <guid>https://dev.to/arunmozhi_varman_k/how-i-built-pop-upz-an-always-on-top-floating-web-player-using-chromes-document-pip-api-5544</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever wanted to keep an eye on a chat, check a stock ticker, monitor a build status board, or scroll through Hacker News while working inside other applications? &lt;/p&gt;

&lt;p&gt;Typically, we are forced to resize multiple windows or use second monitors. While browsers support Picture-in-Picture (PiP), the traditional PiP API is strictly limited to &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; elements. &lt;/p&gt;

&lt;p&gt;To solve this, I built &lt;strong&gt;Pop-Upz&lt;/strong&gt;—a lightweight Chrome extension that detaches &lt;em&gt;any&lt;/em&gt; webpage into a fully borderless, floating, always-on-top window. &lt;/p&gt;

&lt;p&gt;In this post, I’ll walk through how I utilized the modern &lt;strong&gt;Document Picture-in-Picture API&lt;/strong&gt; and bypassed cross-origin security restrictions to keep any website floating over your desktop.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ The Core Technology: Document Picture-in-Picture API
&lt;/h2&gt;

&lt;p&gt;Introduced in Chrome 116, the &lt;strong&gt;Document Picture-in-Picture API&lt;/strong&gt; makes it possible to open an always-on-top window that can be populated with arbitrary HTML content. &lt;/p&gt;

&lt;p&gt;Unlike video-only PiP, this opens up endless utility. We can inject an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; inside the PiP window to render an entire website.&lt;/p&gt;

&lt;p&gt;Here is the basic framework to launch a Document PiP window from a user gesture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Request the Picture-in-Picture Window&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentPictureInPicture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Populate the PiP window's document body&lt;/span&gt;
&lt;span class="nx"&gt;pipWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  &amp;lt;html&amp;gt;
    &amp;lt;body&amp;gt;
      &amp;lt;iframe src="https://example.com" style="width:100%; height:100%; border:none;"&amp;gt;&amp;lt;/iframe&amp;gt;
    &amp;lt;/body&amp;gt;
  &amp;lt;/html&amp;gt;
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;pipWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛑 The Challenge: Bypassing CSP and Frame Restrictions
&lt;/h2&gt;

&lt;p&gt;If you try to load major websites (like YouTube, GitHub, or LinkedIn) inside an iframe, you will immediately run into console errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Refused to display 'https://...' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Websites use headers like &lt;code&gt;X-Frame-Options&lt;/code&gt; and &lt;code&gt;Content-Security-Policy&lt;/code&gt; (CSP) to prevent clickjacking attacks by forbidding their pages from being embedded in iframes on other domains.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Manifest V3 &lt;code&gt;declarativeNetRequest&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To bypass this limitation for our floating player, we can leverage Chrome's declarative rules to strip these blocking headers &lt;em&gt;only&lt;/em&gt; when the iframe is requested inside our extension's subframe context.&lt;/p&gt;

&lt;p&gt;Here is the ruleset configuration (&lt;code&gt;rules.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"modifyHeaders"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"responseHeaders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"X-Frame-Options"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Frame-Options"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Content-Security-Policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remove"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"resourceTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sub_frame"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By removing these headers dynamically at the browser engine level, we can frame any website seamlessly inside our floating window.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Solving the Chrome Transient Activation Bug
&lt;/h2&gt;

&lt;p&gt;One of the trickiest parts of building this extension was handling Chrome's &lt;strong&gt;User Gesture requirement&lt;/strong&gt;. The browser prevents scripts from launching pop-ups programmatically unless triggered by an explicit click.&lt;/p&gt;

&lt;p&gt;If you have any asynchronous delay (&lt;code&gt;await&lt;/code&gt; statements or microtask yields) between the user's click and the &lt;code&gt;requestWindow()&lt;/code&gt; call, Chrome immediately invalidates the gesture token, throwing this error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Could not launch Picture-in-Picture window. Please interact with the page first."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To solve this, I designed Pop-Upz to run the PiP instantiation &lt;strong&gt;completely synchronously&lt;/strong&gt; inside the button click handler, only running the document generation logic inside the resolving &lt;code&gt;.then()&lt;/code&gt; promise block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Synchronously bound to the click event to preserve transient gesture&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentPictureInPicture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestWindow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;pipWindow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Safe to write document asynchronously here!&lt;/span&gt;
  &lt;span class="nx"&gt;pipWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
  &lt;span class="nx"&gt;pipWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎨 Clean and Minimalist Design
&lt;/h2&gt;

&lt;p&gt;Instead of adding heavy settings menus or floating control bars that clutter the screen, Pop-Upz detaches into a &lt;strong&gt;100% borderless, full-bleed viewport&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Users can trigger it in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clicking the &lt;strong&gt;Pop-Upz Toolbar Icon&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right-clicking anywhere on a webpage&lt;/strong&gt; and selecting &lt;strong&gt;"Pop Out with Pop-Upz ✦"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once detached, you can drag the corners of the native window to resize it to any layout you prefer (Mobile view, Tablet view, Wide, etc.).&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Check Out the Project
&lt;/h2&gt;

&lt;p&gt;The project is fully open-source and ready to load as a developer unpacked extension.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/AMV0027/Pop-Upz" rel="noopener noreferrer"&gt;AMV0027/Pop-Upz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/arunmozhivarmank/" rel="noopener noreferrer"&gt;Arunmozhi Varman K&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to clone the repo, try it out, and star the project if you find it useful! Let me know in the comments how you plan to use always-on-top floating web pages in your workflow.&lt;/p&gt;

</description>
      <category>api</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
