<?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: FujiDevv</title>
    <description>The latest articles on DEV Community by FujiDevv (@fujidevv).</description>
    <link>https://dev.to/fujidevv</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F976185%2F788763a4-1c8c-424b-bd56-bd64225b073d.jpeg</url>
      <title>DEV Community: FujiDevv</title>
      <link>https://dev.to/fujidevv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fujidevv"/>
    <language>en</language>
    <item>
      <title>How I Built a 100 percent On-Device Tab Region GIF Recorder as a Chrome Extension</title>
      <dc:creator>FujiDevv</dc:creator>
      <pubDate>Mon, 27 Jul 2026 08:02:52 +0000</pubDate>
      <link>https://dev.to/fujidevv/how-i-built-a-100-percent-on-device-tab-region-gif-recorder-as-a-chrome-extension-5776</link>
      <guid>https://dev.to/fujidevv/how-i-built-a-100-percent-on-device-tab-region-gif-recorder-as-a-chrome-extension-5776</guid>
      <description>&lt;p&gt;Most web-based screen recorders work by streaming video frame data to cloud servers for rendering, encoding, and storage. While convenient for team collaboration, uploading raw frame buffers creates privacy and security risks when capturing internal staging environments, admin dashboards, or client tools containing sensitive data.&lt;/p&gt;

&lt;p&gt;To solve this, I built CstWeave—a privacy-first Chrome Extension that captures tab regions and encodes clean GIFs or HD WebMs 100 percent on-device directly inside local browser memory.&lt;/p&gt;

&lt;p&gt;In this post, I will break down the architecture, technical decisions, and how to build a custom client-side GIF encoding pipeline within Chrome Extension Manifest V3.&lt;/p&gt;

&lt;p&gt;TECHNICAL ARCHITECTURE (MANIFEST V3)&lt;/p&gt;

&lt;p&gt;Under Manifest V3, Chrome extensions rely on ephemeral Service Workers rather than persistent background pages. Because Service Workers lack access to the HTML DOM and canvas elements, performing frame capture and pixel manipulation requires a decoupled offscreen architecture.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Scoped UI with Shadow DOM (selection.ts)&lt;br&gt;
To let users drag and crop any region on a webpage without CSS bleeding or layout shift, the selection interface is mounted inside an isolated Shadow DOM container. It renders the drag-to-crop selection overlay , manages floating active recording controls and countdown timers , and shows an overlay modal for instant clip previews, clipboard copying, or saving.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Background Orchestrator (background.ts)&lt;br&gt;
The Service Worker handles state orchestration, fetches media stream IDs via chrome.tabCapture, and manages the lifecycle of the offscreen document.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offscreen Document and Encoding Engine (offscreen.ts)&lt;br&gt;
The offscreen canvas document processes video stream frames and handles all GIF and WebM rendering off main UI threads to prevent tab throttling. For WebM capture, it uses the native Web MediaRecorder API over canvas.captureStream() with optional system audio mixing. For GIFs, it runs a custom pure-TypeScript encoding pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;THE CUSTOM TYPESCRIPT GIF ENGINE&lt;/p&gt;

&lt;p&gt;Browser-native APIs like MediaRecorder do not output raw animated .gif files out of the box. To generate lightweight GIFs on-device without external WASM binaries or server-side render queues, CstWeave implements a pure TypeScript encoding pipeline:&lt;/p&gt;

&lt;p&gt;Frame Capture: Uses a setTimeout loop drawing the tab stream to a canvas element, avoiding background tab requestAnimationFrame throttling.&lt;/p&gt;

&lt;p&gt;Color Palette Generation: Runs a Median-Cut algorithm on sampled frame pixels (sampling roughly every 8th frame and 4th pixel) to compute an optimal 256-color palette.&lt;/p&gt;

&lt;p&gt;Color Quantization: Applies optional Floyd-Steinberg dithering to smooth gradients across frames.&lt;/p&gt;

&lt;p&gt;LZW Compression: Encodes pixel indices into variable code-width LZW dictionary chunks directly inside Uint8Array typed arrays.&lt;/p&gt;

&lt;p&gt;Blob Assembly: Concatenates array chunks into a final binary Blob with image/gif MIME type for direct local export or clipboard pasting.&lt;/p&gt;

&lt;p&gt;KEY FEATURES&lt;/p&gt;

&lt;p&gt;100 percent Local Processing: Captured frames remain strictly inside local RAM and CPU memory—zero media ever leaves your machine.&lt;/p&gt;

&lt;p&gt;Instant Hotkey Workflow: Press Alt+Shift+G (or Command+Shift+G / Option+Shift+G on Mac) on any tab to select a region and record.&lt;/p&gt;

&lt;p&gt;No Forced Watermarks: Clean exports across both free (Lite) and paid (Pro) tiers.&lt;/p&gt;

&lt;p&gt;Freemium Lifetime Model: Lite is free forever (5s GIF clips); Pro is a single $9.99 purchase (not a subscription) for longer clips, higher FPS, HD WebM, and audio capture.&lt;/p&gt;

&lt;p&gt;CHECK IT OUT&lt;/p&gt;

&lt;p&gt;If you work on sensitive staging environments, log bug reproductions for Jira/GitHub, or want clean GIF/WebM exports without cloud bloat, feel free to give CstWeave a try!&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://cstweave.com" rel="noopener noreferrer"&gt;https://cstweave.com&lt;/a&gt; Browser Support: Chrome 116+, Microsoft Edge, Brave &lt;/p&gt;

&lt;p&gt;I would love to hear your feedback on the offscreen architecture or custom GIF encoder!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>typescript</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I rebuilt 90s desktop pets for the modern web (using 100% Local AI in the browser)</title>
      <dc:creator>FujiDevv</dc:creator>
      <pubDate>Thu, 25 Jun 2026 15:15:21 +0000</pubDate>
      <link>https://dev.to/fujidevv/i-rebuilt-90s-desktop-pets-for-the-modern-web-using-100-local-ai-in-the-browser-1hhl</link>
      <guid>https://dev.to/fujidevv/i-rebuilt-90s-desktop-pets-for-the-modern-web-using-100-local-ai-in-the-browser-1hhl</guid>
      <description>&lt;p&gt;If you used a computer in the late 90s or early 2000s, you probably remember the sheer joy (and chaos) of virtual desktop pets. Whether it was a little sheep walking on your taskbar, a Shimeji dropping from the top of your screen, or the infamous Clippy judging your Word documents—they added a ton of personality to our screens.                                                                                                    &lt;/p&gt;

&lt;p&gt;I really missed that feeling, so I decided to bring it back for the modern web.                             &lt;/p&gt;

&lt;p&gt;But I didn't want to just make a looping GIF. I wanted to build a virtual companion that actually "reads the room."                                                                                                      &lt;/p&gt;

&lt;p&gt;Meet Arcrawls — an open-source, context-aware browser mascot.&lt;br&gt;&lt;br&gt;
                                                                                                                                                &lt;a href="url"&gt;&lt;/a&gt;&lt;a href="https://arcrawls.com" rel="noopener noreferrer"&gt;https://arcrawls.com&lt;/a&gt;                                                                                  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tech Stack&lt;/strong&gt;                                                                                      &lt;/p&gt;

&lt;p&gt;Building a browser extension that interacts with the DOM is tricky enough, but adding AI into the mix made it a really fun engineering challenge. Here is what I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Core Extension: TypeScript &amp;amp; Vite&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Landing Page: Vue 3 &amp;amp; TailwindCSS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extension API: Manifest V3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI &amp;amp; Machine Learning: Chrome's Built-in AI (Gemini Nano) &amp;amp; ONNX Runtime (WebAssembly)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Challenge: 100% Local Offline AI&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
                                                                                                              The core feature of Arcrawls is that it analyzes the text and sentiment of the webpage you are currently reading. If you are reading a depressing news article, the pet acts sad. If your developer console is throwing a bunch of red errors, it puts on a hard hat and looks confused.&lt;/p&gt;

&lt;p&gt;The easiest way to do this would have been to just grab the &lt;code&gt;document.body.innerText&lt;/code&gt; and fire it off to an OpenAI API endpoint.   But I firmly believe browser extensions should not be sending your private reading habits to the cloud. Instead, the entire AI sentiment analysis engine runs 100% locally and offline directly inside your browser. I achieved this using a hybrid approach: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Chrome's Built-in Gemini Nano: Arcrawls taps into the new, experimental &lt;code&gt;window.ai&lt;/code&gt; API built directly into modern Chrome browsers. This allows the extension to leverage the local Gemini Nano model to perform complex sentiment and context analysis without downloading massive model weights. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ONNX Runtime for WebAssembly: For fallback support and lighter, faster inference tasks (like quick zero-shot classification), the extension runs on-device machine learning via ONNX Runtime compiled to WebAssembly (WASM). This runs directly within the extension's sandboxed Service Worker.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because everything happens locally, zero data leaves your device,     inference is incredibly fast, and there are absolutely zero recurring cloud API costs to worry about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bringing it to life with Physics&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;I implemented a custom spring physics engine that runs via a          &lt;code&gt;requestAnimationFrame&lt;/code&gt; loop. The pet recalculates its target position based on where you are scrolling and uses spring dampening to crawl, jump, and interact with the edges of your viewport naturally. Getting the physics to run buttery-smooth in Vanilla TS while injecting it into a shadow DOM (to prevent the host site's CSS from bleeding into the pet's UI) was a massive learning experience!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's Open Source!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Arcrawls is a passion project, and it is 100% free and open-source. Building for Manifest V3 (especially trying to run WASM inside Service Workers) was a huge learning curve with plenty of weird CSP and fetching bugs to overcome.&lt;/p&gt;

&lt;p&gt;I'd absolutely love for you to try it out! If you are interested in extension development, local AI, or just want a little crab keeping you company while you debug, check out the code.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://dev.tourl"&gt;https://arcrawls.com&lt;/a&gt;&lt;br&gt;
GitHub Repo: fujiDevv/context-aware-browser-pet &lt;a href="https://dev.tourl"&gt;https://github.com/fujiDevv/context-aware-browser-pet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think in the comments! Has anyone else experimented with Chrome's Gemini Nano or ONNX Runtime inside browser extensions? I'd love to swap notes on how you handled the memory      constraints! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
