šŸ”„ Build Your Own AI-Powered Chrome Extension šŸ§©

Santhosh Vijayabaskar - Oct 30 - - Dev Community

Ever find yourself scrolling through endless articles and news pages, just hoping to get the main points and move on? Yeah, me too. Itā€™s exhausting, right? šŸ˜© Well, hereā€™s a little shortcut weā€™re going to build together! šŸ’Ŗ

Weā€™re going to make a Chrome extension that scrapes content from any webpage šŸŒ, whips up a quick summary with a bit of AI magic šŸŖ„, andā€”hereā€™s the fun partā€”reads it out loud for you šŸ”Š. Super convenient, donā€™t you think?

By the end, youā€™ll have something that not only saves you time ā±ļø but also gives you that little boost of, ā€˜Hey, I built this!ā€™ šŸ˜Ž

Hereā€™s what weā€™re working with:

  1. Cheerio: Think of Cheerio as the friend that helps us skim through HTML and grab the important stuff. Itā€™ll make sure weā€™re only pulling what we need from each page.
  2. Hugging Face Transformers: These AI models do the heavy lifting with summarization. Weā€™ll use them to shrink long pages down to the essentialsā€”no unnecessary fluff.
  3. ResponsiveVoice.js: This adds the final touch by reading out the summary. Itā€™s surprisingly simple to use, and there are lots of voices and languages to pick from.

By the end, youā€™ll have built an AI-powered Chrome extension, and along the way, youā€™ll pick up some solid skills in JavaScript, web scraping, and using AI models. Donā€™t worry if youā€™re new to thisā€”Iā€™ll guide you through it, and by the end, youā€™ll have something genuinely cool and useful to show off. Letā€™s get started! šŸš€


šŸŖ„ Step 1: Setting Up Your Chrome Extension

First, letā€™s get the basic Chrome extension structure in place. Weā€™ll create three files for this setup:

  • manifest.json - Configures our Chrome extension.
  • popup.html - The user interface for the extension.
  • popup.js - Contains JavaScript code to interact with the content and run summarization.

Create the Project Structure

Set up your project folder with the following structure:

/summarize-tool
|-- manifest.json
|-- popup.html
|-- popup.js
Enter fullscreen mode Exit fullscreen mode

1.1 manifest.json: The Blueprint of Your Extension
The manifest file is what Chrome reads to know how to run and interact with our extension. Hereā€™s what it should look like:

{
  "manifest_version": 3,
  "name": "Summarize Tool",
  "version": "1.0",
  "description": "A Chrome extension that scrapes and summarizes content from any webpage.",
  "permissions": ["scripting", "tabs", "activeTab"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "host_permissions": ["<all_urls>"]
}
Enter fullscreen mode Exit fullscreen mode

This setup tells Chrome what the extension does, which files are in use, and what permissions it needs (like accessing the current webpageā€™s content).

1.2 popup.html: Creating the Extension Interface
Now letā€™s add some basic HTML to give users a button to trigger the summarization and text-to-voice features.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Summarize Tool</title>
</head>
<body>
    <h2>Summarize This Page</h2>
    <button id="summarize-btn">Summarize</button>
    <div id="summary" style="margin-top: 15px; font-size: 14px;"></div>
    <button id="read-summary" style="margin-top: 15px;">Read Out Loud</button>
    <script src="popup.js"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

This simple layout gives us two buttons: one for summarizing the page and another for reading the summary out loud.

šŸ” Step 2: Extracting Content with DOMParser

Now that our extension is set up, letā€™s dive into getting the content we want from any webpage. Weā€™ll use DOMParser to retrieve and parse HTML directly in the Chrome extension environment.

šŸ¤” Why DOMParser?
DOMParser allows us to extract the main text from a webpage without needing external libraries, making it efficient and compatible with Chrome extensions.

Hereā€™s what weā€™ll do:

When the "Summarize" button is clicked, the DOMParser will grab the main content on the page.
This content will then be passed along to Hugging Face for summarization.
Hereā€™s the code for popup.js to extract the content:

document.getElementById("summarize-btn").addEventListener("click", async () => {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

    chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: getPageContent,
    }, (results) => {
        if (results && results[0] && results[0].result) {
            const htmlContent = results[0].result;
            parseAndSummarizeContent(htmlContent);
        }
    });
});

// Function to retrieve the pageā€™s HTML content
function getPageContent() {
    return document.documentElement.outerHTML;
}

// Function to parse the HTML content and extract the main text
function parseAndSummarizeContent(htmlContent) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(htmlContent, "text/html");

    // Extract specific elements or paragraphs
    const paragraphs = Array.from(doc.querySelectorAll("p"));
    let bodyText = paragraphs.slice(0, 3).map(p => p.innerText).join(" ");

    // Limit to 500 characters for API to prevent server errors
    if (bodyText.length > 500) {
        bodyText = bodyText.substring(0, 500);
    }

    // Send the trimmed text for summarization
    summarizeContent(bodyText);
}
Enter fullscreen mode Exit fullscreen mode

Now, whenever the button is clicked, this function will grab the main content of the page, trimmed to avoid API overload.

šŸ§  Step 3: Summarizing Content with Hugging Face Transformers

Next up, letā€™s condense that content with Hugging Face Transformers!

šŸ¤” Why Hugging Face?
Hugging Face provides AI models that can do heavy-duty tasks, like turning a long article into a short summary. Weā€™ll use their summarizer model to cut down the text into the key points.

To do this, youā€™ll need an API key from Hugging Face. Once you have that, hereā€™s how to set up the API call in popup.js:

async function summarizeContent(content, retries = 3, delay = 1000) {
    const API_URL = "https://api-inference.huggingface.co/models/sshleifer/distilbart-cnn-12-6";
    const API_KEY = "YOUR_HUGGING_FACE_API_KEY";

    console.log("Sending content to summarize:", content); // Log the content being sent

    for (let attempt = 1; attempt <= retries; attempt++) {
        try {
            const response = await fetch(API_URL, {
                method: "POST",
                headers: {
                    "Authorization": `Bearer ${API_KEY}`,
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({ inputs: content })
            });

            if (response.ok) {
                const summaryData = await response.json();
                const summary = summaryData[0]?.summary_text || "Summary not available.";
                document.getElementById("summary").innerText = summary;
                return;
            } else if (response.status === 503) {
                console.error(`Attempt ${attempt}: Server unavailable (503). Retrying in ${delay}ms...`);
                await new Promise(resolve => setTimeout(resolve, delay));
                delay *= 2; // Exponential backoff
            } else {
                console.error("Error in response:", response.status, response.statusText);
                document.getElementById("summary").innerText = "Error: Unable to fetch summary.";
                return;
            }

        } catch (error) {
            console.error("Error:", error);
            document.getElementById("summary").innerText = "Error: Unable to fetch summary.";
            return;
        }
    }

    document.getElementById("summary").innerText = "Error: Unable to fetch summary after multiple attempts.";
}
Enter fullscreen mode Exit fullscreen mode

This code sends the content to Hugging Face, and the response will be a short summary that gets displayed in our popup. Now youā€™ve got the power of AI summarization with retry logic!

šŸ”Š Step 4: Adding Text-to-Voice with Web Speech API

Letā€™s add the finishing touch by allowing users to hear the summary! The Web Speech API provides a simple way to convert text to speech directly in the browser.

In popup.js, add the functionality to read out the summary:

document.getElementById("read-summary").addEventListener("click", () => {
    const summaryText = document.getElementById("summary").innerText;
    if (summaryText) {
        const utterance = new SpeechSynthesisUtterance(summaryText);
        utterance.lang = "en-US"; // Adjust language as needed
        window.speechSynthesis.speak(utterance);
    } else {
        alert("No summary available to read.");
    }
});
Enter fullscreen mode Exit fullscreen mode

Now when you click ā€œRead Out Loud,ā€ the summary will be spoken, giving you a hands-free experience!

Step 5: Testing the Extension šŸš€

Time to see it in action!

Head over to chrome://extensions/, enable Developer Mode, and click Load unpacked to load your extension.

Image description

Now, open a webpage, click the extension icon, and test the summarization and voice features.

Image description

Itā€™s a good idea to test on different pages to make sure itā€™s working smoothly.

āœØ Step 6: Fine-Tuning and Enhancements

Here are a few ideas to make this extension even better:

  • Experiment with Summarization Models: Hugging Face has different models, so try others to see if one works better for your needs.

  • Add a Language Selector: ResponsiveVoice supports multiple languages, so why not add a selector for users who prefer a different language?

  • Adjust Summary Length: Give users the option to choose between short, medium, and long summaries for more customization.

And thatā€™s it! šŸŽ‰ Youā€™ve built a powerful, time-saving Chrome extension that combines scraping, summarizing, and text-to-speech. Not only does it save time, but itā€™s also a tool you can genuinely use every day. Enjoy showing off your creation!

P.S.: I ran into a few NPM errors specific to my setupā€”if you hit any snags, feel free to reach out for help!

šŸŒ You can also learn more about my work and projects at https://santhoshvijayabaskar.com


Credits:
Photo by Firmbee.com on Unsplash

. . . . . .