Behind Building ‘Loom’ with Gemini 3 Flash & FastAPI

Mithul Pranav | May 25, 2026 min read

If you spend any amount of time on technical subreddits or YouTube tutorials, you know the pain. Someone posts a question—maybe their laptop is throwing a weird error code, or their code won’t compile. You know exactly how to fix it. You spend five minutes typing out a beautiful, perfectly formatted step-by-step solution. You hit “Post.”

And then you scroll down and realize someone else posted the exact same solution ten minutes ago.

When a thread has hundreds (or thousands) of comments, it’s impossible to read through every single one just to check if your two cents have already been deposited. It wastes the helper’s time, clutters the creator’s comment section, and buries the actual signal under a mountain of repetitive noise.

That was the inspiration for Loom, my submission for the 2026 Google Gemini 3 Hackathon. I wanted to build a tool that acts as a “pre-flight check” for your digital discourse.

Here’s a look at why I built it, how it works, and the tech stack that makes it tick.


What is Loom?

Loom is a context-aware browser extension that sits quietly in your browser while you type on YouTube or Reddit. When you’re drafting a comment, you can click a button to run an analysis.

Loom grabs your draft, fetches the top 250 comments in the thread, and reads the actual context of the page (the YouTube video description or the Reddit post body). It feeds all of this into Gemini 3 Flash and asks: “Is this redundant? Has this been answered? Is this relevant?”

If your question was already answered by the creator in the description, Loom tells you. If someone else already made your point, Loom highlights it. And if you have a unique angle, it offers suggestions to make your comment even sharper. It even features a chat mode so you can interrogate the thread context directly.


The Tech Stack: Under the Hood

To make this feel seamless, it had to be fast. Waiting 10 seconds for an AI to tell you not to post a comment is terrible UX. Here is the stack I used to keep latency low:

  • AI Engine: Google Gemini 3 Flash Preview (configured with a ‘Medium’ thinking level for solid semantic reasoning without huge latency hits).
  • Backend: Python + FastAPI. FastAPI is brilliant for this because of its out-of-the-box async support.
  • Frontend: JavaScript (Manifest V3 Chrome Extension) with a custom Glassmorphism UI injected straight into the DOM.
  • Data Sources: YouTube Data API v3 and the Reddit JSON API.
  • Tunneling: ngrok (to bridge the local FastAPI server to the live browser extension during development).

Fetching the Context

The backend doesn’t just scrape blindly. For YouTube, it extracts the video_id from the URL, calls the YouTube API to get the video description, and then pulls the top-level comment threads.

For Reddit, I used a fun little trick: if you append .json to the end of a Reddit URL, Reddit serves up the entire post and comment tree as a JSON object. I wrote a recursive parser to flatten this tree and grab the highest-upvoted comments to feed into Gemini’s context window.

The System Prompt

The real magic of Loom lies in how Gemini is prompted. I pass the page context and the thread data as variables, then give Gemini strict rules:

  1. Don’t just look for keyword matches; look for intent.
  2. If the user’s draft is redundant, cite the specific author who already said it.
  3. Keep responses concise and conversational.

The Biggest Challenge: Single Page Applications (SPAs)

The hardest part of building the frontend wasn’t the AI integration; it was dealing with modern web architecture.

YouTube and Reddit are Single Page Applications. When you click a new video on YouTube, the page doesn’t actually reload—the URL changes and the DOM updates dynamically. Initially, this meant Loom would get “stuck.” You’d click a new video, start typing, and Loom would analyze your comment against the previous video’s comments.

The Fix: I couldn’t rely on standard page load events. Instead, I implemented a robust URL observer using setInterval in my content.js file:

let currentUrl = window.location.href;

setInterval(() => {
    if (window.location.href !== currentUrl) {
        currentUrl = window.location.href;
        resetLoom(true); // Wipes the AI's memory and resets the UI for the new context
    }
}, 1500);