<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[mellowtel]]></title><description><![CDATA[mellowtel]]></description><link>https://blog.mellowtel.com</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 13:51:32 GMT</lastBuildDate><atom:link href="https://blog.mellowtel.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Mellowtel Performance Analysis: Real-World Impact Testing]]></title><description><![CDATA[Mellowtel is an open-source library that helps browser extension developers monetize their work through consensual bandwidth sharing. The library allows users to opt-in to share their unused bandwidth with AI labs and startups who need access to publ...]]></description><link>https://blog.mellowtel.com/performance</link><guid isPermaLink="true">https://blog.mellowtel.com/performance</guid><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Wed, 04 Dec 2024 21:43:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733347339031/759b67fc-8b30-46b7-a120-7021de8ae07f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Mellowtel is an open-source library that helps browser extension developers monetize their work through consensual bandwidth sharing. The library allows users to opt-in to share their unused bandwidth with AI labs and startups who need access to public websites, with developers receiving a portion of the revenue. To better understand its performance characteristics, we conducted a series of benchmark tests to measure its impact on system resources.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Y4cNWyuDCEA">https://youtu.be/Y4cNWyuDCEA</a></div>
<p> </p>
<h2 id="heading-test-setup-and-methodology">Test Setup and Methodology</h2>
<p>We conducted a stress test by sequentially chaining 10 requests through Mellowtel - an extreme scenario that would rarely occur in real-world usage, where requests are typically more sporadic and spread out over time. Each request was executed one after another in rapid succession, allowing us to measure the maximum potential impact on:</p>
<ul>
<li><p>Network bandwidth utilization</p>
</li>
<li><p>CPU usage (M2 Silicon chip)</p>
</li>
<li><p>RAM consumption (16GB total system RAM)</p>
</li>
<li><p>Request distribution and handling</p>
</li>
</ul>
<h2 id="heading-results-and-analysis">Results and Analysis</h2>
<h3 id="heading-network-performance">Network Performance</h3>
<ul>
<li><p>Total Data Transferred: 18.56 MB</p>
</li>
<li><p>Total Requests: 10</p>
</li>
</ul>
<h3 id="heading-system-resource-impact">System Resource Impact</h3>
<ul>
<li><p>RAM Usage: Maximum increase of 0.43% (on 16GB system)</p>
</li>
<li><p>CPU Usage: Maximum increase of 0.0001% (M2 Silicon)</p>
</li>
<li><p>No visible spikes or significant changes in resource utilization during testing</p>
</li>
</ul>
<h3 id="heading-request-breakdown">Request Breakdown</h3>
<p>The test generated various types of requests:</p>
<ul>
<li><p>Script requests: 496 (2.52 MB)</p>
</li>
<li><p>Stylesheet requests: 33 (270.77 KB)</p>
</li>
<li><p>Image requests: 285 (15.01 MB)</p>
</li>
<li><p>XMLHttpRequests: 82 (248.47 KB)</p>
</li>
<li><p>Font requests: 34 (532.55 KB)</p>
</li>
<li><p>Other requests: 20 (1.79 KB)</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733347209113/b3ba6d8a-2d6a-4015-84b8-151a8c149a00.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-system-impact">System Impact</h3>
<p>Even under this rapid-fire testing scenario, our measurements showed remarkably low resource utilization. With a maximum RAM delta of just 0.43% and CPU usage increase of 0.0001%, Mellowtel's impact on system performance is negligible. The video monitoring confirmed that the bandwidth sharing operates efficiently in the background without any noticeable impact on system performance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733347120567/350a7646-c73d-4eee-a36b-dc6a2fc39134.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-impact-on-user-experience">Impact on User Experience</h2>
<p>The test results demonstrate that Mellowtel's bandwidth-sharing mechanism operates with remarkable efficiency, even when handling back-to-back requests. Users can expect even lower resource usage in typical scenarios, as real-world usage patterns are more sporadic with natural delays between requests. During testing, we observed:</p>
<ul>
<li><p>No noticeable system slowdown</p>
</li>
<li><p>Minimal resource overhead (less than 0.5% RAM usage)</p>
</li>
<li><p>Controlled bandwidth utilization</p>
</li>
<li><p>Negligible CPU impact (0.0001% increase)</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Our benchmark testing reveals that Mellowtel successfully achieves its goal of utilizing spare bandwidth while maintaining a light system footprint, even under stress conditions that exceed normal usage patterns. This makes it a viable option for browser extension developers looking to monetize their work without compromising user experience.</p>
<p>These results align with Mellowtel's design philosophy of creating a sustainable ecosystem for browser extensions that balances developer monetization with user experience. With such minimal resource impact - fractional percentages for both CPU and RAM usage even under rapid sequential testing - users can confidently opt into bandwidth sharing without concerns about system performance degradation.</p>
]]></content:encoded></item><item><title><![CDATA[Where chrome extensions are stored]]></title><description><![CDATA[Chrome extensions are stored in specific locations on your computer, depending on your operating system and Chrome profile. Here's a comprehensive guide to finding where Chrome extensions are stored:
Windows
On Windows, Chrome extensions are typicall...]]></description><link>https://blog.mellowtel.com/where-chrome-extensions-are-stored</link><guid isPermaLink="true">https://blog.mellowtel.com/where-chrome-extensions-are-stored</guid><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Mon, 11 Nov 2024 22:03:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731362617756/182adc3f-0e44-4b76-9b7f-eaa5928d9c15.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Chrome extensions are stored in specific locations on your computer, depending on your operating system and Chrome profile. Here's a comprehensive guide to finding where Chrome extensions are stored:</p>
<h2 id="heading-windows">Windows</h2>
<p>On Windows, Chrome extensions are typically stored in the following location:</p>
<pre><code class="lang-plaintext">C:\Users\[YourUsername]\AppData\Local\Google\Chrome\User Data\Default\Extensions
</code></pre>
<p>If you're using multiple Chrome profiles, replace "Default" with the specific profile name, such as "Profile 1" or "Profile 2".</p>
<h2 id="heading-macos">macOS</h2>
<p>For Mac users, Chrome extensions can be found in:</p>
<pre><code class="lang-plaintext">~/Library/Application Support/Google/Chrome/Default/Extensions
</code></pre>
<p>Similarly, if you have multiple profiles, replace "Default" with the appropriate profile name.</p>
<h2 id="heading-linux">Linux</h2>
<p>Linux users can locate Chrome extensions in:</p>
<pre><code class="lang-plaintext">~/.config/google-chrome/Default/Extensions
</code></pre>
<p>Again, adjust the path for different profiles if necessary.</p>
<h2 id="heading-finding-the-exact-location">Finding the Exact Location</h2>
<p>To find the precise location of Chrome extensions on your system:</p>
<ol>
<li><p>Open Chrome and navigate to <code>chrome://version/</code></p>
</li>
<li><p>Look for the "Profile Path" entry</p>
</li>
<li><p>The extensions folder will be located within this path, under a folder named "Extensions"</p>
</li>
</ol>
<h2 id="heading-extension-folder-structure">Extension Folder Structure</h2>
<p>Within the Extensions folder, you'll find subdirectories named with unique IDs corresponding to each installed extension. These IDs can be found in the Chrome Web Store URL for the extension or in the <code>chrome://extensions</code> page when developer mode is enabled.</p>
<h2 id="heading-unpacked-extensions">Unpacked Extensions</h2>
<p>It's important to note that unpacked extensions (those loaded for development purposes) are not stored in the same location. They remain in the directory from which they were loaded.</p>
<h2 id="heading-accessing-extension-data">Accessing Extension Data</h2>
<p>While the extension files are stored in these locations, user data for extensions is typically stored separately using Chrome's storage APIs. This data is not directly accessible in the file system but can be viewed using developer tools:</p>
<ol>
<li><p>Go to <code>chrome://extensions</code></p>
</li>
<li><p>Find the extension and click on "Inspect views: background page"</p>
</li>
<li><p>In the developer tools, go to the Application tab</p>
</li>
<li><p>Expand the Storage section to view Local Storage and other storage mechanisms used by the extension</p>
</li>
</ol>
<p>Understanding where Chrome extensions are stored can be helpful for developers and power users who need to access or manage extension files directly. However, for most users, interacting with extensions through Chrome's interface is sufficient and recommended.</p>
]]></content:encoded></item><item><title><![CDATA[Creating an Options Page for Your Chrome Extension]]></title><description><![CDATA[An options page allows users to customize your Chrome extension's behavior. This guide will walk you through creating and implementing an options page in your extension.
What is an Options Page?
An options page is a dedicated page that allows users t...]]></description><link>https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension</link><guid isPermaLink="true">https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 20:25:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727641492103/159a8cc4-6b48-4b14-a92a-2a011e5a969b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>An options page allows users to customize your Chrome extension's behavior. This guide will walk you through creating and implementing an options page in your extension.</p>
<h2 id="heading-what-is-an-options-page">What is an Options Page?</h2>
<p>An options page is a dedicated page that allows users to configure settings for your extension. It's a great way to make your extension more flexible and user-friendly.</p>
<p>If you're new to Chrome extension development, start with our guide on <a target="_blank" href="https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide">How to Create Your First Chrome Extension</a>.</p>
<h2 id="heading-steps-to-create-an-options-page">Steps to Create an Options Page</h2>
<h3 id="heading-1-create-the-options-page-html">1. Create the Options Page HTML</h3>
<p>First, create a file named <code>options.html</code> in your extension's directory:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Extension Options<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>
    Favorite color:
    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"color"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"red"</span>&gt;</span>red<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"green"</span>&gt;</span>green<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"blue"</span>&gt;</span>blue<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"yellow"</span>&gt;</span>yellow<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"save"</span>&gt;</span>Save<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"options.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="heading-2-create-the-options-page-javascript">2. Create the Options Page JavaScript</h3>
<p>Create a file named <code>options.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Saves options to chrome.storage</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">save_options</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> color = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'color'</span>).value;
  chrome.storage.sync.set({
    <span class="hljs-attr">favoriteColor</span>: color
  }, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Update status to let user know options were saved.</span>
    <span class="hljs-keyword">var</span> status = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'status'</span>);
    status.textContent = <span class="hljs-string">'Options saved.'</span>;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      status.textContent = <span class="hljs-string">''</span>;
    }, <span class="hljs-number">750</span>);
  });
}

<span class="hljs-comment">// Restores select box and checkbox state using the preferences</span>
<span class="hljs-comment">// stored in chrome.storage.</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">restore_options</span>(<span class="hljs-params"></span>) </span>{
  chrome.storage.sync.get({
    <span class="hljs-attr">favoriteColor</span>: <span class="hljs-string">'red'</span> <span class="hljs-comment">// default value</span>
  }, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">items</span>) </span>{
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'color'</span>).value = items.favoriteColor;
  });
}

<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, restore_options);
<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'save'</span>).addEventListener(<span class="hljs-string">'click'</span>, save_options);
</code></pre>
<p>This script uses the <a target="_blank" href="https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data">Chrome Extension Storage API</a> to save and retrieve user preferences.</p>
<h3 id="heading-3-register-the-options-page-in-manifestjson">3. Register the Options Page in manifest.json</h3>
<p>Add the options page to your <code>manifest.json</code>:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"options_page"</span>: <span class="hljs-string">"options.html"</span>
}
</code></pre>
<h2 id="heading-using-options-in-your-extension">Using Options in Your Extension</h2>
<p>You can access the saved options in other parts of your extension, such as <a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">background scripts</a> or <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a>:</p>
<pre><code class="lang-javascript">chrome.storage.sync.get({
  <span class="hljs-attr">favoriteColor</span>: <span class="hljs-string">'red'</span> <span class="hljs-comment">// default value</span>
}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">items</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'The user'</span>s favorite color is <span class="hljs-string">' + items.favoriteColor);
});</span>
</code></pre>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p>Keep the options simple and easy to understand</p>
</li>
<li><p>Provide default values for all options</p>
</li>
<li><p>Use appropriate input types (checkboxes, radio buttons, select dropdowns) for different types of options</p>
</li>
<li><p>Provide immediate feedback when options are saved</p>
</li>
<li><p>Consider using the options page to allow users to customize API endpoints or provide API keys for <a target="_blank" href="https://blog.mellowtel.com/making-api-calls-in-chrome-extensions">Making API Calls in Chrome Extensions</a></p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>An options page is a powerful tool for making your Chrome extension more flexible and user-friendly. By following this guide, you've learned how to create an options page, save user preferences, and use those preferences in your extension.</p>
<p>As you develop more complex extensions, consider how you can use options pages in conjunction with other extension features to create a customizable and powerful user experience.</p>
]]></content:encoded></item><item><title><![CDATA[Making API Calls in Chrome Extensions]]></title><description><![CDATA[Making API calls is a common requirement for many Chrome extensions. This guide will walk you through the process of making API calls from different parts of your Chrome extension using modern JavaScript practices.
Prerequisites
Before making API cal...]]></description><link>https://blog.mellowtel.com/making-api-calls-in-chrome-extensions</link><guid isPermaLink="true">https://blog.mellowtel.com/making-api-calls-in-chrome-extensions</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 20:22:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727641113220/c3fe19e2-117d-4bca-b9a9-c7e57ec12015.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Making API calls is a common requirement for many Chrome extensions. This guide will walk you through the process of making API calls from different parts of your Chrome extension using modern JavaScript practices.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before making API calls, ensure you've set up your basic extension structure. If you're new to this, check out our guide on <a target="_blank" href="https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide">How to Create Your First Chrome Extension</a>.</p>
<h2 id="heading-steps-to-make-api-calls">Steps to Make API Calls</h2>
<h3 id="heading-1-request-permissions">1. Request Permissions</h3>
<p>First, request permission to make network requests in your <code>manifest.json</code>:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"manifest_version"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My API Extension"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"permissions"</span>: [<span class="hljs-string">"https://api.example.com/"</span>],
  <span class="hljs-attr">"host_permissions"</span>: [<span class="hljs-string">"https://api.example.com/"</span>]
}
</code></pre>
<p>Replace <a target="_blank" href="https://api.example.com/"><code>https://api.example.com/</code></a> with the base URL of the API you're calling. Note that in Manifest V3, we use both <code>permissions</code> and <code>host_permissions</code> for network requests.</p>
<h3 id="heading-2-making-the-api-call">2. Making the API Call</h3>
<p>You can use the <code>fetch</code> API with <code>async/await</code> to make network requests. Here's a basic example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-built_in">console</span>.log(data);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
  }
}

fetchData();
</code></pre>
<p>This code uses <code>async/await</code> to handle the asynchronous nature of the <code>fetch</code> call, making it easier to read and maintain.</p>
<h3 id="heading-3-handling-cors">3. Handling CORS</h3>
<p>If you're making calls to a third-party API, you might encounter CORS (Cross-Origin Resource Sharing) issues. To resolve this, you may need to make the call from a service worker (background script) instead of a content script.</p>
<h2 id="heading-making-api-calls-from-different-contexts">Making API Calls from Different Contexts</h2>
<h3 id="heading-from-service-workers-background-scripts">From Service Workers (Background Scripts)</h3>
<p>Service workers in Manifest V3 can use async/await directly:</p>
<pre><code class="lang-javascript">chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">request, sender, sendResponse</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (request.action === <span class="hljs-string">'fetchData'</span>) {
    fetchDataAndRespond(sendResponse);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;  <span class="hljs-comment">// Will respond asynchronously</span>
  }
});

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchDataAndRespond</span>(<span class="hljs-params">sendResponse</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://api.example.com/data'</span>);
    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    sendResponse({<span class="hljs-attr">data</span>: data});
  } <span class="hljs-keyword">catch</span> (error) {
    sendResponse({<span class="hljs-attr">error</span>: error.toString()});
  }
}
</code></pre>
<h3 id="heading-from-content-scripts">From Content Scripts</h3>
<p>While <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a> can make API calls directly, it's often better to relay the call through a service worker to avoid CORS issues:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchDataFromBackground</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> chrome.runtime.sendMessage({<span class="hljs-attr">action</span>: <span class="hljs-string">'fetchData'</span>});
    <span class="hljs-keyword">if</span> (response.data) {
      <span class="hljs-built_in">console</span>.log(response.data);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">console</span>.error(response.error);
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
  }
}

fetchDataFromBackground();
</code></pre>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p>Error Handling: Always include proper error handling in your API calls.</p>
</li>
<li><p>Use async/await: It makes asynchronous code more readable and easier to maintain.</p>
</li>
<li><p>Respect API Rate Limits: Implement appropriate throttling or caching mechanisms.</p>
</li>
<li><p>Secure Storage of API Keys: If your API requires authentication, store keys securely. Consider using the <a target="_blank" href="https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data">Chrome Extension Storage API</a> for sensitive data.</p>
</li>
<li><p>Handle Network Changes: Be prepared for offline scenarios or network interruptions.</p>
</li>
</ol>
<h2 id="heading-security-considerations">Security Considerations</h2>
<ol>
<li><p>Never expose sensitive API keys in your extension code. Use environment variables or secure storage methods.</p>
</li>
<li><p>Always use HTTPS for API calls to ensure data privacy and integrity.</p>
</li>
<li><p>Validate and sanitize all data received from APIs before using it in your extension.</p>
</li>
<li><p>Be cautious about the permissions you request. Only ask for what you need.</p>
</li>
</ol>
<h2 id="heading-using-the-fetch-api-with-options">Using the Fetch API with Options</h2>
<p>For more complex API calls, you can pass options to the <code>fetch</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">postData</span>(<span class="hljs-params">url = <span class="hljs-string">''</span>, data = {}</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(data),
    });
    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.json();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
  }
}

<span class="hljs-comment">// Usage</span>
postData(<span class="hljs-string">'https://api.example.com/data'</span>, { <span class="hljs-attr">answer</span>: <span class="hljs-number">42</span> })
  .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  });
</code></pre>
<h2 id="heading-handling-authentication">Handling Authentication</h2>
<p>If your API requires authentication, you might need to include an API key or token in your requests. Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchWithAuth</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-keyword">const</span> API_KEY = <span class="hljs-keyword">await</span> getApiKey(); <span class="hljs-comment">// Implement this function to securely retrieve your API key</span>
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url, {
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${API_KEY}</span>`</span>
      }
    });
    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.json();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
  }
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Making API calls is a powerful way to extend the functionality of your Chrome extension. By following this guide, you've learned how to make API calls from different parts of your extension, handle errors, and deal with common issues like CORS.</p>
<p>As you develop more complex extensions, consider how you can use API calls in conjunction with other extension features, such as <a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">service workers</a>, <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a>, and <a target="_blank" href="https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension">options pages</a>, to create a rich and dynamic user experience.</p>
<p>Remember to always prioritize security and user privacy when working with APIs in your extensions. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Chrome Extension Storage API: Saving and Retrieving Data]]></title><description><![CDATA[The Chrome Extension Storage API provides a way to store, retrieve, and track changes to user data in your extension. This guide will walk you through using the Storage API in your Chrome extension.
What is the Chrome Extension Storage API?
The Stora...]]></description><link>https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data</link><guid isPermaLink="true">https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 20:17:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727641001145/36e2285c-f5ce-4852-9423-f0c942ba689d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Chrome Extension Storage API provides a way to store, retrieve, and track changes to user data in your extension. This guide will walk you through using the Storage API in your Chrome extension.</p>
<h2 id="heading-what-is-the-chrome-extension-storage-api">What is the Chrome Extension Storage API?</h2>
<p>The Storage API allows you to store and retrieve data in a way that's optimized for extension performance. It provides two main types of storage:</p>
<ol>
<li><p><a target="_blank" href="http://chrome.storage"><code>chrome.storage</code></a><code>.sync</code>: Syncs data across all Chrome browsers that the user is logged into.</p>
</li>
<li><p><a target="_blank" href="http://chrome.storage"><code>chrome.storage</code></a><code>.local</code>: Stores data locally on the user's device.</p>
</li>
</ol>
<p>If you're new to Chrome extension development, start with our guide on <a target="_blank" href="https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide">How to Create Your First Chrome Extension</a>.</p>
<h2 id="heading-using-the-storage-api">Using the Storage API</h2>
<h3 id="heading-1-request-permission">1. Request Permission</h3>
<p>First, request permission to use the Storage API in your <code>manifest.json</code>:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"permissions"</span>: [<span class="hljs-string">"storage"</span>]
}
</code></pre>
<h3 id="heading-2-saving-data">2. Saving Data</h3>
<p>To save data, use the <code>set</code> method:</p>
<pre><code class="lang-javascript">chrome.storage.sync.set({<span class="hljs-attr">key</span>: value}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Value is set to '</span> + value);
});
</code></pre>
<h3 id="heading-3-retrieving-data">3. Retrieving Data</h3>
<p>To retrieve data, use the <code>get</code> method:</p>
<pre><code class="lang-javascript">chrome.storage.sync.get([<span class="hljs-string">'key'</span>], <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">result</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Value currently is '</span> + result.key);
});
</code></pre>
<h3 id="heading-4-listening-for-changes">4. Listening for Changes</h3>
<p>You can listen for changes to stored data:</p>
<pre><code class="lang-javascript">chrome.storage.onChanged.addListener(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">changes, namespace</span>) </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> [key, { oldValue, newValue }] <span class="hljs-keyword">of</span> <span class="hljs-built_in">Object</span>.entries(changes)) {
    <span class="hljs-built_in">console</span>.log(
      <span class="hljs-string">`Storage key "<span class="hljs-subst">${key}</span>" in namespace "<span class="hljs-subst">${namespace}</span>" changed.`</span>,
      <span class="hljs-string">`Old value was "<span class="hljs-subst">${oldValue}</span>", new value is "<span class="hljs-subst">${newValue}</span>".`</span>
    );
  }
});
</code></pre>
<h2 id="heading-storage-limits">Storage Limits</h2>
<p>It's important to be aware of the storage limits when using the Chrome Extension Storage API:</p>
<h3 id="heading-chromestoragehttpchromestoragesync"><a target="_blank" href="http://chrome.storage">chrome.storage</a>.sync</h3>
<ul>
<li><p>Total storage limit: 100KB of data synced across devices</p>
</li>
<li><p>Per-item limit: 8KB</p>
</li>
<li><p>Maximum number of items: 512</p>
</li>
</ul>
<h3 id="heading-chromestoragehttpchromestoragelocal"><a target="_blank" href="http://chrome.storage">chrome.storage</a>.local</h3>
<ul>
<li><p>Total storage limit: 10MB (may be less on some devices)</p>
</li>
<li><p>Per-item limit: 5MB</p>
</li>
<li><p>No limit on the number of items</p>
</li>
</ul>
<p>Be mindful of these limits when designing your extension. If you need to store larger amounts of data, consider using <a target="_blank" href="http://chrome.storage"><code>chrome.storage</code></a><code>.local</code> or even IndexedDB for very large datasets.</p>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p>Use <code>sync</code> storage for user preferences and small amounts of data.</p>
</li>
<li><p>Use <code>local</code> storage for larger amounts of data or data that doesn't need to be synced.</p>
</li>
<li><p>Be mindful of storage limits: <code>sync</code> has stricter limits than <code>local</code>.</p>
</li>
<li><p>Always handle errors and edge cases when reading from or writing to storage.</p>
</li>
</ol>
<h2 id="heading-using-storage-in-different-contexts">Using Storage in Different Contexts</h2>
<p>The Storage API can be used in various parts of your extension:</p>
<ul>
<li><p>In <a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">background scripts</a> for managing global state.</p>
</li>
<li><p>In <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a> for storing page-specific data.</p>
</li>
<li><p>In popup scripts for saving user interactions.</p>
</li>
<li><p>In <a target="_blank" href="https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension">options pages</a> for storing user preferences.</p>
</li>
</ul>
<h2 id="heading-making-api-calls-with-stored-data">Making API Calls with Stored Data</h2>
<p>You might want to use stored data when <a target="_blank" href="https://blog.mellowtel.com/making-api-calls-in-chrome-extensions">Making API Calls in Chrome Extensions</a>, such as using stored API keys or user preferences to customize API requests.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The Chrome Extension Storage API is a powerful tool for managing data in your extension. By following this guide, you've learned how to save, retrieve, and listen for changes to stored data.</p>
<p>As you develop more complex extensions, consider how you can use the Storage API in conjunction with other extension features to create a seamless user experience.</p>
]]></content:encoded></item><item><title><![CDATA[Using Content Scripts in Chrome Extensions: A Complete Guide]]></title><description><![CDATA[Content scripts are a powerful feature of Chrome extensions that allow you to interact directly with web pages. This guide will walk you through creating and implementing content scripts in your Chrome extension.
What are Content Scripts?
Content scr...]]></description><link>https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide</link><guid isPermaLink="true">https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 19:33:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727638352329/6208ed5a-1776-4bc4-bd3d-67cd35a4ff5c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Content scripts are a powerful feature of Chrome extensions that allow you to interact directly with web pages. This guide will walk you through creating and implementing content scripts in your Chrome extension.</p>
<h2 id="heading-what-are-content-scripts">What are Content Scripts?</h2>
<p>Content scripts are JavaScript files that run in the context of web pages. They can read details of the web pages the browser visits, make changes to them, and pass information to their parent extension.</p>
<p>If you're new to Chrome extension development, start with our guide on <a target="_blank" href="https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide">How to Create Your First Chrome Extension</a>.</p>
<h2 id="heading-creating-and-implementing-content-scripts">Creating and Implementing Content Scripts</h2>
<h3 id="heading-1-create-the-content-script-file">1. Create the Content Script File</h3>
<p>First, create a new file in your extension's directory, typically named <code>content.js</code>.</p>
<h3 id="heading-2-write-your-content-script">2. Write Your Content Script</h3>
<p>Here's a basic example of a content script:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Content script loaded'</span>);

<span class="hljs-comment">// Change the background color of the page</span>
<span class="hljs-built_in">document</span>.body.style.backgroundColor = <span class="hljs-string">'lightblue'</span>;

<span class="hljs-comment">// Listen for messages from the extension</span>
chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">request, sender, sendResponse</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (request.action === <span class="hljs-string">'getPageTitle'</span>) {
    sendResponse({<span class="hljs-attr">title</span>: <span class="hljs-built_in">document</span>.title});
  }
});
</code></pre>
<p>This script logs a message, changes the page's background color, and listens for messages from the extension.</p>
<h3 id="heading-3-register-the-content-script-in-manifestjson">3. Register the Content Script in manifest.json</h3>
<p>To tell Chrome about your content script, register it in your <code>manifest.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"manifest_version"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My Extension"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"An extension with a content script"</span>,
  <span class="hljs-attr">"content_scripts"</span>: [
    {
      <span class="hljs-attr">"matches"</span>: [<span class="hljs-string">"&lt;all_urls&gt;"</span>],
      <span class="hljs-attr">"js"</span>: [<span class="hljs-string">"content.js"</span>]
    }
  ]
}
</code></pre>
<h3 id="heading-4-communicating-with-content-scripts">4. Communicating with Content Scripts</h3>
<p>You can send messages to your content script from other parts of your extension, like <a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">background scripts</a>:</p>
<pre><code class="lang-javascript">chrome.tabs.query({<span class="hljs-attr">active</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">currentWindow</span>: <span class="hljs-literal">true</span>}, <span class="hljs-function">(<span class="hljs-params">tabs</span>) =&gt;</span> {
  chrome.tabs.sendMessage(tabs[<span class="hljs-number">0</span>].id, {<span class="hljs-attr">action</span>: <span class="hljs-string">"getPageTitle"</span>}, <span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Page title:'</span>, response.title);
  });
});
</code></pre>
<h2 id="heading-best-practices-for-content-scripts">Best Practices for Content Scripts</h2>
<ol>
<li><p>Keep them lightweight: Content scripts should be efficient to avoid slowing down web page loading.</p>
</li>
<li><p>Use event listeners: React to specific events rather than running continuous loops.</p>
</li>
<li><p>Be cautious with page modifications: Ensure your changes don't break the functionality of the web pages.</p>
</li>
<li><p>Use <a target="_blank" href="http://chrome.storage">chrome.storage</a> for persistent data: This allows you to share data between content scripts and other parts of your extension.</p>
</li>
</ol>
<h2 id="heading-making-api-calls-from-content-scripts">Making API Calls from Content Scripts</h2>
<p>While it's possible to make API calls directly from content scripts, it's often better to do this from a <a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">background scrip</a><a target="_blank" href="background-script-guide">t</a> for security reasons. For more information, see our guide on <a target="_blank" href="https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data">Making API Calls in Chrome Extensions</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Content scripts are a crucial tool for Chrome extensions that need to interact with web pages. By following this guide, you've learned how to create, implement, and use content scripts in your extension.</p>
]]></content:encoded></item><item><title><![CDATA[How to Create a Service Worker for Chrome Extensions]]></title><description><![CDATA[Service workers are a key component of modern Chrome extensions, replacing the older background scripts. This guide will walk you through creating and implementing a service worker in your Chrome extension.
What is a Service Worker?
A service worker ...]]></description><link>https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 19:30:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727638116675/254230f1-1233-4fc3-8e77-992036268ae7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Service workers are a key component of modern Chrome extensions, replacing the older background scripts. This guide will walk you through creating and implementing a service worker in your Chrome extension.</p>
<h2 id="heading-what-is-a-service-worker">What is a Service Worker?</h2>
<p>A service worker in a Chrome extension is a script that runs separately from web pages. It's designed to handle events, perform tasks, and manage state for your extension. Key points to understand:</p>
<ol>
<li><p>Service workers are event-based and do not run continuously.</p>
</li>
<li><p>They can be started and stopped by the browser as needed.</p>
</li>
<li><p>They are short-lived and can be terminated and restarted between events.</p>
</li>
<li><p>They don't have access to the DOM or window object.</p>
</li>
</ol>
<h2 id="heading-steps-to-create-a-service-worker">Steps to Create a Service Worker</h2>
<h3 id="heading-1-create-the-service-worker-file">1. Create the Service Worker File</h3>
<p>First, create a new file in your extension's directory, typically named <code>background.js</code> (despite being a service worker).</p>
<h3 id="heading-2-write-your-service-worker-script">2. Write Your Service Worker Script</h3>
<p>Here's a basic example of a service worker:</p>
<pre><code class="lang-javascript">chrome.runtime.onInstalled.addListener(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Extension installed'</span>);
});

<span class="hljs-comment">// Listen for messages from other parts of your extension</span>
chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">request, sender, sendResponse</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (request.action === <span class="hljs-string">'performTask'</span>) {
    <span class="hljs-comment">// Perform some task</span>
    sendResponse({<span class="hljs-attr">result</span>: <span class="hljs-string">'Task completed'</span>});
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// Indicates we will respond asynchronously</span>
});
</code></pre>
<p>This script sets up listeners for the extension installation event and for messages from other parts of your extension.</p>
<h3 id="heading-3-register-the-service-worker-in-manifestjson">3. Register the Service Worker in manifest.json</h3>
<p>To tell Chrome about your service worker, you need to register it in your <code>manifest.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"manifest_version"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My Extension"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"An extension with a service worker"</span>,
  <span class="hljs-attr">"background"</span>: {
    <span class="hljs-attr">"service_worker"</span>: <span class="hljs-string">"background.js"</span>
  }
}
</code></pre>
<h2 id="heading-using-the-service-worker">Using the Service Worker</h2>
<p>You can communicate with your service worker from other parts of your extension, like popup scripts or content scripts, using <code>chrome.runtime.sendMessage</code>:</p>
<pre><code class="lang-plaintext">javascriptCopychrome.runtime.sendMessage({action: 'performTask'}, response =&gt; {
  console.log(response.result);  // Outputs: "Task completed"
});
</code></pre>
<h2 id="heading-best-practices-for-service-workers">Best Practices for Service Workers</h2>
<ol>
<li><p>Keep them lightweight: Service workers should be efficient as they are terminated and restarted frequently.</p>
</li>
<li><p>Use event listeners: Structure your code around events rather than continuous processes.</p>
</li>
<li><p>Avoid using DOM or window: Service workers don't have access to these objects.</p>
</li>
<li><p>Use chrome.storage for persistent data: This allows data to persist between service worker restarts. Learn more in our <a target="_blank" href="https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data">Chrome Extension Storage API guide</a>.</p>
</li>
<li><p>Handle errors gracefully: Be prepared for your service worker to be terminated at any time.</p>
</li>
</ol>
<h2 id="heading-common-use-cases-for-service-workers">Common Use Cases for Service Workers</h2>
<ol>
<li><p>Listening for browser events (like tab updates, bookmark changes, etc.)</p>
</li>
<li><p>Managing extension state</p>
</li>
<li><p>Handling cross-origin requests that aren't allowed in content scripts</p>
</li>
<li><p>Scheduling alarms or timers using <code>chrome.alarms</code></p>
</li>
</ol>
<h2 id="heading-debugging-service-workers">Debugging Service Workers</h2>
<ol>
<li><p>Use <code>console.log()</code> statements in your service worker code.</p>
</li>
<li><p>Open the background page from the extension management page (chrome://extensions) by clicking on the "Service Worker" link for your extension.</p>
</li>
<li><p>Use the Chrome DevTools to debug your service worker.</p>
</li>
</ol>
<h2 id="heading-making-api-calls-from-service-workers">Making API Calls from Service Workers</h2>
<p>Service workers are ideal for making API calls, as they can run independently of the extension's UI. For more information on this, check out our article on <a target="_blank" href="https://blog.mellowtel.com/making-api-calls-in-chrome-extensions">Making API Calls in Chrome Extensions</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Service workers are a crucial component for creating powerful and responsive Chrome extensions. By following this guide, you've learned how to create, implement, and use a service worker in your extension.</p>
<p>Remember, the event-driven nature of service workers is different from the old background scripts. This new model is more efficient but requires a different approach to structuring your extension's background logic.</p>
<p>As you develop more complex extensions, you'll find service workers invaluable for managing state, handling events, and performing background tasks. Consider how you can use them in conjunction with <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a> and <a target="_blank" href="https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension">options pages</a> to create a comprehensive extension.</p>
<p>Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[How to Create Your First Chrome Extension: A Step-by-Step Guide]]></title><description><![CDATA[Creating a Chrome extension is a great way to enhance your browsing experience and learn about web development. This guide will walk you through creating your very first Chrome extension.
What is a Chrome Extension?
A Chrome extension is a small soft...]]></description><link>https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-create-your-first-chrome-extension-a-step-by-step-guide</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 29 Sep 2024 19:21:51 GMT</pubDate><content:encoded><![CDATA[<p>Creating a Chrome extension is a great way to enhance your browsing experience and learn about web development. This guide will walk you through creating your very first Chrome extension.</p>
<h2 id="heading-what-is-a-chrome-extension">What is a Chrome Extension?</h2>
<p>A Chrome extension is a small software program that customizes the Chrome browsing experience. Extensions can modify functionality, change the appearance of web pages, or add new features to the Chrome browser.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Basic knowledge of HTML, CSS, and JavaScript</p>
</li>
<li><p>Google Chrome browser installed</p>
</li>
<li><p>A text editor (like Visual Studio Code, Sublime Text, or even Notepad)</p>
</li>
</ul>
<h2 id="heading-step-1-create-your-project-directory">Step 1: Create Your Project Directory</h2>
<ol>
<li><p>Create a new folder on your computer for your extension.</p>
</li>
<li><p>Name it something relevant to your extension's purpose.</p>
</li>
</ol>
<h2 id="heading-step-2-create-the-manifest-file">Step 2: Create the Manifest File</h2>
<p>The manifest file is the heart of your Chrome extension. It tells Chrome about your extension, its capabilities, and the resources it needs.</p>
<ol>
<li><p>In your project folder, create a new file named <code>manifest.json</code>.</p>
</li>
<li><p>Add the following content to <code>manifest.json</code>:</p>
</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"manifest_version"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My First Extension"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"A simple Chrome extension."</span>,
  <span class="hljs-attr">"action"</span>: {
    <span class="hljs-attr">"default_popup"</span>: <span class="hljs-string">"popup.html"</span>
  }
}
</code></pre>
<h2 id="heading-step-3-create-the-popup-html">Step 3: Create the Popup HTML</h2>
<p>This will be the user interface of your extension when the user clicks on its icon.</p>
<ol>
<li><p>Create a new file named <code>popup.html</code> in your project folder.</p>
</li>
<li><p>Add the following content:</p>
</li>
</ol>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My First Chrome Extension<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, Chrome Extension!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"changeColor"</span>&gt;</span>Change Color<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"popup.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-step-4-add-functionality-with-javascript">Step 4: Add Functionality with JavaScript</h2>
<ol>
<li><p>Create a new file named <code>popup.js</code> in your project folder.</p>
</li>
<li><p>Add the following content:</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> changeColorButton = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'changeColor'</span>);
  changeColorButton.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">document</span>.body.style.backgroundColor = getRandomColor();
  });
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRandomColor</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> letters = <span class="hljs-string">'0123456789ABCDEF'</span>;
  <span class="hljs-keyword">var</span> color = <span class="hljs-string">'#'</span>;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">6</span>; i++) {
    color += letters[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">16</span>)];
  }
  <span class="hljs-keyword">return</span> color;
}
</code></pre>
<p>This script adds functionality to the button in your popup, changing the background color randomly when clicked.</p>
<h2 id="heading-step-5-load-your-extension-in-chrome">Step 5: Load Your Extension in Chrome</h2>
<ol>
<li><p>Open Google Chrome and navigate to <code>chrome://extensions/</code>.</p>
</li>
<li><p>Enable "Developer mode" in the top right corner.</p>
</li>
<li><p>Click "Load unpacked" and select your extension directory.</p>
</li>
</ol>
<p>Congratulations! You've just created and loaded your first Chrome extension.</p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that you've created your first extension, you can explore more advanced features:</p>
<ul>
<li><p><a target="_blank" href="https://blog.mellowtel.com/how-to-create-a-service-worker-for-chrome-extensions">Create a background script</a> to run tasks in the background.</p>
</li>
<li><p>Use <a target="_blank" href="https://blog.mellowtel.com/using-content-scripts-in-chrome-extensions-a-complete-guide">content scripts</a> to interact with web pages.</p>
</li>
<li><p>Learn how to <a target="_blank" href="https://blog.mellowtel.com/chrome-extension-storage-api-saving-and-retrieving-data">store and retrieve data</a> in your extension.</p>
</li>
<li><p><a target="_blank" href="https://blog.mellowtel.com/making-api-calls-in-chrome-extensions">Make API calls</a> to interact with external services.</p>
</li>
<li><p>Add an <a target="_blank" href="https://blog.mellowtel.com/creating-an-options-page-for-your-chrome-extension">options page</a> to make your extension customizable.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've taken your first steps into the world of Chrome extension development. As you continue to learn and experiment, you'll be able to create more complex and powerful extensions to enhance your browsing experience.</p>
<p>Remember, the key to becoming proficient is practice and exploration. Don't hesitate to refer back to this guide and explore the Chrome Extension documentation for more advanced features and best practices.</p>
<p>Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[How to Debug Offscreen Pages in Chrome Extension Manifest V3]]></title><description><![CDATA[Debugging offscreen pages in Chrome extensions using Manifest V3 can be challenging, but there are effective methods to overcome this issue. Here are the primary approaches:
1. Use chrome://inspect/#other
Navigate to chrome://inspect/#other in Chrome...]]></description><link>https://blog.mellowtel.com/how-to-debug-offscreen-pages-in-chrome-extension-manifest-v3</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-debug-offscreen-pages-in-chrome-extension-manifest-v3</guid><category><![CDATA[chrome extension]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Wed, 25 Sep 2024 00:51:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727225388497/16a0753d-93d2-4f02-8890-c731bb27127c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Debugging offscreen pages in Chrome extensions using Manifest V3 can be challenging, but there are effective methods to overcome this issue. Here are the primary approaches:</p>
<h2 id="heading-1-use-chromeinspectother">1. Use chrome://inspect/#other</h2>
<p>Navigate to chrome://inspect/#other in Chrome to find and debug your offscreen page. This method allows direct access to the offscreen page's console and debugging tools.</p>
<h2 id="heading-2-implement-a-logging-relay-system">2. Implement a logging relay system</h2>
<p>If the offscreen window closes too quickly, create a helper function in the offscreen page to send logs to the background script:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> log = <span class="hljs-keyword">async</span> (...args) =&gt; chrome.runtime.sendMessage({
  <span class="hljs-attr">target</span>: <span class="hljs-string">'background'</span>,
  <span class="hljs-attr">type</span>: <span class="hljs-string">'log'</span>,
  <span class="hljs-attr">data</span>: args,
});
</code></pre>
<p>Add a listener in the background script to receive and display these logs:</p>
<pre><code class="lang-javascript">chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (message.target === <span class="hljs-string">'background'</span> &amp;&amp; message.type === <span class="hljs-string">'log'</span>) {
    <span class="hljs-built_in">console</span>.log(...message.data);
  }
});
</code></pre>
<p>Use the <code>log</code> function in your offscreen page:</p>
<pre><code class="lang-javascript">log(<span class="hljs-string">'clipboard'</span>);
</code></pre>
<h2 id="heading-3-inspect-from-the-chrome-extensions-page">3. Inspect from the Chrome Extensions page</h2>
<ol>
<li><p>Go to chrome://extensions</p>
</li>
<li><p>Find your extension and open its details</p>
</li>
<li><p>Locate the "Inspect views" section</p>
</li>
<li><p>Click on your offscreen page link</p>
</li>
</ol>
<p>This method opens Chrome DevTools for the offscreen page, allowing you to view console logs and debug effectively.</p>
]]></content:encoded></item><item><title><![CDATA[Resolving "Uncaught (in promise) Error: Error: Adapter 'http' is not available in the build"]]></title><description><![CDATA[When developing Chrome extensions, you may encounter the "Uncaught (in promise) Error: Error: Adapter 'http' is not available in the build” error when using Axios. This article explores how to solve this issue using the Fetch API with an async/await ...]]></description><link>https://blog.mellowtel.com/resolving-uncaught-in-promise-error-error-adapter-http-is-not-available-in-the-build</link><guid isPermaLink="true">https://blog.mellowtel.com/resolving-uncaught-in-promise-error-error-adapter-http-is-not-available-in-the-build</guid><category><![CDATA[chrome extension]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Wed, 25 Sep 2024 00:41:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727224737841/865ca0a4-6ec4-4f3a-a84a-7dc1ad961e76.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developing Chrome extensions, you may encounter the "Uncaught (in promise) Error: Error: Adapter 'http' is not available in the build” error when using Axios. This article explores how to solve this issue using the Fetch API with an async/await approach.</p>
<h2 id="heading-the-problem">The Problem</h2>
<p>Chrome extension service workers don't support XMLHttpRequest, which Axios relies on. This leads to the error:</p>
<pre><code class="lang-plaintext">Uncaught (in promise) Error: Error: Adapter 'http' is not available in the build
</code></pre>
<h2 id="heading-the-solution-fetch-api-with-asyncawait">The Solution: Fetch API with Async/Await</h2>
<p>Instead of using Axios, we'll use the Fetch API, which is natively supported in service workers. We'll implement this using async/await for cleaner, more readable code.</p>
<h3 id="heading-implementing-fetch-with-asyncawait">Implementing Fetch with Async/Await</h3>
<p>Here's a detailed example of how to use Fetch with async/await in your Chrome extension:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params">url, token</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>,
      <span class="hljs-attr">credentials</span>: <span class="hljs-string">"include"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
        <span class="hljs-string">"Authorization"</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${token}</span>`</span>,
        <span class="hljs-string">"Cookie"</span>: token  <span class="hljs-comment">// If needed</span>
      }
    });

    <span class="hljs-keyword">if</span> (!response.ok) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`HTTP error! status: <span class="hljs-subst">${response.status}</span>`</span>);
    }

    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-keyword">return</span> data;
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Fetch error:"</span>, error);
    <span class="hljs-keyword">throw</span> error;
  }
}
</code></pre>
<h3 id="heading-using-the-async-function">Using the Async Function</h3>
<p>To use this function in your service worker or other parts of your extension, you can do:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDataFetch</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetchData(<span class="hljs-string">"https://api.example.com/data"</span>, <span class="hljs-string">"your-auth-token"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Data received:"</span>, data);
    <span class="hljs-comment">// Process your data here</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error fetching data:"</span>, error);
    <span class="hljs-comment">// Handle errors appropriately</span>
  }
}

<span class="hljs-comment">// Call the function</span>
handleDataFetch();
</code></pre>
<h2 id="heading-benefits-of-asyncawait-approach">Benefits of Async/Await Approach</h2>
<ol>
<li><p><strong>Readability</strong>: The code flows more like synchronous code, making it easier to understand.</p>
</li>
<li><p><strong>Error Handling</strong>: Try/catch blocks can handle both synchronous and asynchronous errors.</p>
</li>
<li><p><strong>Sequential Execution</strong>: Easily handle multiple asynchronous operations in sequence.</p>
</li>
</ol>
<h2 id="heading-best-practices-for-asyncawait-in-chrome-extensions">Best Practices for Async/Await in Chrome Extensions</h2>
<ol>
<li><p><strong>Error Handling</strong>: Always use try/catch blocks to handle potential errors.</p>
</li>
<li><p><strong>Avoid Blocking</strong>: Remember that <code>await</code> still blocks execution in the current function. Use <code>Promise.all()</code> for concurrent operations.</p>
</li>
<li><p><strong>Request Timeouts</strong>: Implement request timeouts to prevent hanging:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> timeout = <span class="hljs-number">5000</span>; <span class="hljs-comment">// 5 seconds</span>

 <span class="hljs-keyword">const</span> fetchWithTimeout = <span class="hljs-keyword">async</span> (url, options, timeout) =&gt; {
   <span class="hljs-keyword">const</span> controller = <span class="hljs-keyword">new</span> AbortController();
   <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> controller.abort(), timeout);

   <span class="hljs-keyword">try</span> {
     <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(url, {
       ...options,
       <span class="hljs-attr">signal</span>: controller.signal
     });
     <span class="hljs-built_in">clearTimeout</span>(id);
     <span class="hljs-keyword">return</span> response;
   } <span class="hljs-keyword">catch</span> (error) {
     <span class="hljs-built_in">clearTimeout</span>(id);
     <span class="hljs-keyword">if</span> (error.name === <span class="hljs-string">'AbortError'</span>) {
       <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Request timed out'</span>);
     }
     <span class="hljs-keyword">throw</span> error;
   }
 };
</code></pre>
</li>
<li><p><strong>Caching</strong>: Implement caching to improve performance:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> cache = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

 <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchWithCache</span>(<span class="hljs-params">url, token</span>) </span>{
   <span class="hljs-keyword">if</span> (cache.has(url)) {
     <span class="hljs-keyword">return</span> cache.get(url);
   }

   <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetchData(url, token);
   cache.set(url, data);
   <span class="hljs-keyword">return</span> data;
 }
</code></pre>
</li>
<li><p><strong>Rate Limiting</strong>: Implement a simple rate limiter:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> rateLimiter = {
   <span class="hljs-attr">lastCall</span>: <span class="hljs-number">0</span>,
   <span class="hljs-attr">minInterval</span>: <span class="hljs-number">1000</span>, <span class="hljs-comment">// minimum 1 second between calls</span>

   <span class="hljs-keyword">async</span> limit(fn) {
     <span class="hljs-keyword">const</span> now = <span class="hljs-built_in">Date</span>.now();
     <span class="hljs-keyword">if</span> (now - <span class="hljs-built_in">this</span>.lastCall &lt; <span class="hljs-built_in">this</span>.minInterval) {
       <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-built_in">this</span>.minInterval - (now - <span class="hljs-built_in">this</span>.lastCall)));
     }
     <span class="hljs-built_in">this</span>.lastCall = <span class="hljs-built_in">Date</span>.now();
     <span class="hljs-keyword">return</span> fn();
   }
 };

 <span class="hljs-comment">// Usage</span>
 <span class="hljs-keyword">await</span> rateLimiter.limit(<span class="hljs-function">() =&gt;</span> fetchData(url, token));
</code></pre>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By adopting the Fetch API with async/await in your Chrome extension, you not only resolve the "Adapter 'http' not available" error but also create more maintainable and efficient code. This approach aligns with modern JavaScript practices and provides a solid foundation for handling asynchronous operations in your extension.</p>
<p>Remember to always test your extension thoroughly, especially when making network requests, to ensure it behaves correctly under various conditions. Keep your code modular and follow Chrome's best practices and security guidelines for extension development.</p>
]]></content:encoded></item><item><title><![CDATA[How to Get the Current Tab URL in a Chrome Extension]]></title><description><![CDATA[This guide will show you how to efficiently retrieve the URL of the current tab in a Google Chrome extension using the latest recommended methods.
Prerequisites

Basic knowledge of JavaScript and HTML

Familiarity with Chrome extension development


...]]></description><link>https://blog.mellowtel.com/how-to-get-the-current-tab-url-in-a-chrome-extension</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-get-the-current-tab-url-in-a-chrome-extension</guid><category><![CDATA[chrome extension]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Wed, 25 Sep 2024 00:19:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727223529386/7e981b97-c490-4605-8391-8d66f401de37.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This guide will show you how to efficiently retrieve the URL of the current tab in a Google Chrome extension using the latest recommended methods.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Basic knowledge of JavaScript and HTML</p>
</li>
<li><p>Familiarity with Chrome extension development</p>
</li>
</ul>
<h2 id="heading-steps-to-get-the-current-tab-url">Steps to Get the Current Tab URL</h2>
<ol>
<li><p><strong>Update Your Manifest File</strong></p>
<p> Ensure your <code>manifest.json</code> file includes the necessary permissions:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"permissions"</span>: [
     <span class="hljs-string">"tabs"</span>
   ]
 }
</code></pre>
<p> Alternatively, you can use the <code>activeTab</code> permission for a less intrusive approach:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"permissions"</span>: [
     <span class="hljs-string">"activeTab"</span>
   ]
 }
</code></pre>
</li>
<li><p><strong>Use the Chrome Tabs API</strong></p>
<p> The method to get the current tab URL depends on which part of your extension you're working in:</p>
<p> a) In a background script (background.js):</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// background.js</span>

 <span class="hljs-comment">// Listen for when a tab is updated</span>
 chrome.tabs.onUpdated.addListener(<span class="hljs-function">(<span class="hljs-params">tabId, changeInfo, tab</span>) =&gt;</span> {
   <span class="hljs-comment">// Check if the tab has completed loading</span>
   <span class="hljs-keyword">if</span> (changeInfo.status === <span class="hljs-string">'complete'</span>) {
     <span class="hljs-comment">// Query for the active tab in the current window</span>
     chrome.tabs.query({<span class="hljs-attr">active</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">currentWindow</span>: <span class="hljs-literal">true</span>}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">tabs</span>) </span>{
       <span class="hljs-keyword">if</span> (tabs[<span class="hljs-number">0</span>]) {
         <span class="hljs-keyword">let</span> currentUrl = tabs[<span class="hljs-number">0</span>].url;
         <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Current tab URL:'</span>, currentUrl);

         <span class="hljs-comment">// Here you can perform actions with the URL, such as:</span>
         <span class="hljs-comment">// - Sending it to a server</span>
         <span class="hljs-comment">// - Storing it in chrome.storage</span>
         <span class="hljs-comment">// - Sending a message to a content script</span>
       }
     });
   }
 });
</code></pre>
<p> b) In the JavaScript associated with your popup HTML:</p>
<pre><code class="lang-html"> <span class="hljs-comment">&lt;!-- popup.html --&gt;</span>
 <span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Extension Popup<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"url-display"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"popup.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<pre><code class="lang-javascript"> <span class="hljs-comment">// popup.js</span>
 <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
   chrome.tabs.query({<span class="hljs-attr">active</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">currentWindow</span>: <span class="hljs-literal">true</span>}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">tabs</span>) </span>{
     <span class="hljs-keyword">if</span> (tabs[<span class="hljs-number">0</span>]) {
       <span class="hljs-keyword">let</span> currentUrl = tabs[<span class="hljs-number">0</span>].url;
       <span class="hljs-built_in">console</span>.log(currentUrl);
       <span class="hljs-comment">// Use currentUrl to update popup DOM</span>
       <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'url-display'</span>).textContent = currentUrl;
     }
   });
 });
</code></pre>
<p> c) In a content script (content.js):</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">// content.js</span>

 <span class="hljs-comment">// Get the current page URL</span>
 <span class="hljs-keyword">let</span> currentUrl = <span class="hljs-built_in">window</span>.location.toString();
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Current page URL:'</span>, currentUrl);

 <span class="hljs-comment">// You can now use this URL for various purposes, such as:</span>
 <span class="hljs-comment">// 1. Sending it to the background script</span>
 chrome.runtime.sendMessage({<span class="hljs-attr">action</span>: <span class="hljs-string">"reportURL"</span>, <span class="hljs-attr">url</span>: currentUrl});

 <span class="hljs-comment">// 2. Modifying page content based on the URL</span>
 <span class="hljs-keyword">if</span> (currentUrl.includes(<span class="hljs-string">'example.com'</span>)) {
   <span class="hljs-comment">// Perform some action specific to example.com</span>
 }
</code></pre>
</li>
<li><p><strong>Handle the URL</strong></p>
<p> Once you have the URL, you can use it as needed in your extension.</p>
</li>
</ol>
<h2 id="heading-important-notes">Important Notes</h2>
<ul>
<li><p><strong>Permission Choice</strong>:</p>
<ul>
<li><p>Use <code>"tabs"</code> permission if you need broad access to tab information.</p>
</li>
<li><p>Prefer <code>"activeTab"</code> if you only need access when the user explicitly interacts with your extension, as it's less intrusive.</p>
</li>
</ul>
</li>
<li><p><strong>Window Focus</strong>:</p>
<ul>
<li><p><code>currentWindow: true</code> uses the window where your extension code is running.</p>
</li>
<li><p><code>lastFocusedWindow: true</code> uses the most recently focused window, which may be different if the user has switched windows.</p>
</li>
</ul>
</li>
<li><p><strong>Error Handling</strong>: Always check if the tab exists before accessing its properties.</p>
</li>
<li><p><strong>Asynchronous Nature</strong>: Remember that <code>chrome.tabs.query</code> is asynchronous. Always use the URL inside the callback or use async/await.</p>
</li>
</ul>
<h2 id="heading-best-practices">Best Practices</h2>
<ul>
<li><p>Handle potential errors, such as when tabs API is not available</p>
</li>
<li><p>Consider using async/await for cleaner code if working with newer Chrome versions</p>
</li>
<li><p>Be aware of the context (background, popup HTML, or content script) when accessing the URL</p>
</li>
<li><p>Respect user privacy and handle URL data securely</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Understanding Chrome Extension Files in Developer Tools: What is installHook.js ?]]></title><description><![CDATA[Have you ever noticed unfamiliar files appearing in your Chrome Developer Tools while working on web projects? You're not alone. Many developers, especially those using React, have encountered a file called installHook.js. Let's explore its origins a...]]></description><link>https://blog.mellowtel.com/understanding-chrome-extension-files-in-developer-tools-what-is-installhookjs</link><guid isPermaLink="true">https://blog.mellowtel.com/understanding-chrome-extension-files-in-developer-tools-what-is-installhookjs</guid><category><![CDATA[Browser Extension]]></category><category><![CDATA[chrome extension]]></category><category><![CDATA[React]]></category><category><![CDATA[mellowtel]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Tue, 24 Sep 2024 22:06:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727215554333/17023c54-aee9-48d7-bda2-ab41232ba64d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever noticed unfamiliar files appearing in your Chrome Developer Tools while working on web projects? You're not alone. Many developers, especially those using React, have encountered a file called <code>installHook.js</code>. Let's explore its origins and how you can get rid of it.</p>
<h2 id="heading-what-is-installhookjs">What is installHook.js?</h2>
<p><code>installHook.js</code> is a file commonly associated with the React Developer Tools Chrome extension. It's not part of your project code, but rather a component of the browser extension designed to enhance the development experience for React applications.</p>
<h2 id="heading-key-points-about-installhookjs">Key Points About installHook.js:</h2>
<ol>
<li><p><strong>Origin</strong>: It's loaded by the React Developer Tools extension, not your website.</p>
</li>
<li><p><strong>Purpose</strong>: Helps set up the development environment for React applications.</p>
</li>
<li><p><strong>Impact</strong>: Does not affect your application's performance for end users.</p>
</li>
<li><p><strong>Visibility</strong>: Only appears in Developer Tools, not in production builds.</p>
</li>
</ol>
<h2 id="heading-how-to-identify-and-deactivate-the-responsible-extension">How to Identify and Deactivate the Responsible Extension</h2>
<p>If you're seeing unfamiliar files in your Developer Tools and want to identify or deactivate the responsible extension, follow these steps:</p>
<ol>
<li><p><strong>Identify the File</strong>:</p>
<ul>
<li><p>Open Chrome Developer Tools (F12 or Right-click &gt; Inspect).</p>
</li>
<li><p>Go to the Network tab.</p>
</li>
<li><p>Refresh your page and look for the unfamiliar file (e.g., <code>installHook.js</code>).</p>
</li>
</ul>
</li>
<li><p><strong>Check the File URL</strong>:</p>
<ul>
<li><p>Click on the file in the Network tab to see its details.</p>
</li>
<li><p>Look at the "Request URL" field.</p>
</li>
<li><p>If it starts with <code>chrome-extension://</code>, it's coming from a browser extension.</p>
</li>
</ul>
</li>
<li><p><strong>Note the Extension ID</strong>:</p>
<ul>
<li><p>The URL will look something like this: <code>chrome-extension://fmkadmapgofadopljbjfkapdkoienihi/build/installHook.js</code></p>
</li>
<li><p>The long string of letters after <code>chrome-extension://</code> is the extension ID (in this example, <code>fmkadmapgofadopljbjfkapdkoienihi</code>).</p>
</li>
</ul>
</li>
<li><p><strong>Find the Extension</strong>:</p>
<ul>
<li><p>Open a new tab and navigate to <code>chrome://extensions/</code></p>
</li>
<li><p>In the search bar at the top of the page, paste the extension ID you noted earlier.</p>
</li>
<li><p>The page will filter to show only the matching extension.</p>
</li>
</ul>
</li>
<li><p><strong>Deactivate or Remove the Extension</strong>:</p>
<ul>
<li><p>To temporarily deactivate: Toggle off the blue switch next to the extension.</p>
</li>
<li><p>To remove completely: Click the "Remove" button.</p>
</li>
</ul>
</li>
<li><p><strong>Verify the Change</strong>:</p>
<ul>
<li><p>Return to your original tab and refresh the page.</p>
</li>
<li><p>Check the Network tab in Developer Tools again to confirm that the file is no longer being loaded.</p>
</li>
</ul>
</li>
</ol>
<p>Remember, many extensions (like React Developer Tools) are helpful for development. Only deactivate or remove them if you're sure they're causing issues or if you're doing performance testing.</p>
<h2 id="heading-alternative-methods-to-disable-extensions">Alternative Methods to Disable Extensions</h2>
<p>If you want to disable all extensions temporarily:</p>
<ul>
<li><p>Use Chrome's Incognito Mode, which doesn't load extensions by default.</p>
</li>
<li><p>Launch Chrome with the <code>--disable-extensions</code> flag:</p>
<ul>
<li><p>On Windows: Right-click the Chrome shortcut &gt; Properties &gt; Add <code>--disable-extensions</code> to the end of the "Target" field.</p>
</li>
<li><p>On Mac/Linux: Launch Chrome from the terminal with <code>google-chrome --disable-extensions</code></p>
</li>
</ul>
</li>
</ul>
<p>By following these steps, you can easily identify, deactivate, or remove any extension that's injecting files into your web pages, giving you more control over your development environment.</p>
<h2 id="heading-should-you-be-concerned">Should You Be Concerned?</h2>
<p>Generally, files like <code>installHook.js</code> are harmless and even beneficial for development. However, if you're worried about performance during testing:</p>
<ul>
<li><p>Disable extensions when profiling your application.</p>
</li>
<li><p>Use Chrome's incognito mode or the <code>--disable-extensions</code> flag when launching Chrome.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Solve CORS Issues When Calling Ollama API from a Chrome Extension]]></title><description><![CDATA[Integrating a local Ollama API with a Chrome Extension can be tricky due to CORS restrictions. This guide will walk you through the process of resolving these issues and successfully connecting your extension to Ollama.
The Challenge: 403 Forbidden E...]]></description><link>https://blog.mellowtel.com/how-to-solve-cors-issues-when-calling-ollama-api-from-a-chrome-extension</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-solve-cors-issues-when-calling-ollama-api-from-a-chrome-extension</guid><category><![CDATA[ollama]]></category><category><![CDATA[chrome extension]]></category><category><![CDATA[mellowtel]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Mon, 23 Sep 2024 21:54:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727128401664/b4f5f617-3ee9-4210-bd46-8f72a5d4261e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Integrating a local Ollama API with a Chrome Extension can be tricky due to CORS restrictions. This guide will walk you through the process of resolving these issues and successfully connecting your extension to Ollama.</p>
<h2 id="heading-the-challenge-403-forbidden-error">The Challenge: 403 Forbidden Error</h2>
<p>When attempting to call the Ollama API from a Chrome Extension, you may encounter a 403 Forbidden error. This occurs due to CORS (Cross-Origin Resource Sharing) restrictions, which prevent web applications from making requests to different domains.</p>
<h2 id="heading-solution-configuring-ollama-and-chrome-extension">Solution: Configuring Ollama and Chrome Extension</h2>
<p>To resolve this issue, you need to make changes in both your Ollama configuration and your Chrome Extension's manifest file. Here's how:</p>
<h3 id="heading-1-configure-ollama-to-allow-chrome-extension-origins">1. Configure Ollama to Allow Chrome Extension Origins</h3>
<p>Set the <code>OLLAMA_ORIGIN</code> environment variable to allow Ollama to accept requests from Chrome Extension origins:</p>
<pre><code class="lang-bash">OLLAMA_ORIGINS=chrome-extension://* ollama serve
</code></pre>
<p>This command whitelists all Chrome Extension origins, enabling communication with Ollama.</p>
<h3 id="heading-2-update-your-chrome-extensions-manifest-file">2. Update Your Chrome Extension's Manifest File</h3>
<p>In your <code>manifest.json</code> file, set the permissions and host permissions correctly:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"permissions"</span>: [
    <span class="hljs-string">"tabs"</span>,
    <span class="hljs-string">"activeTab"</span>,
    <span class="hljs-string">"http://localhost/*"</span>,
    <span class="hljs-string">"scripting"</span>
  ],
  <span class="hljs-attr">"host_permissions"</span>: [<span class="hljs-string">"http://localhost/*"</span>]
}
</code></pre>
<p>This configuration grants your extension the necessary permissions to interact with <a target="_blank" href="http://localhost">localhost</a>, where your Ollama instance is running.</p>
<h2 id="heading-implementing-the-api-call">Implementing the API Call</h2>
<p>After making these changes, implement your API call function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateCodeSuggestionFromOllama</span>(<span class="hljs-params">prompt</span>) </span>{
    <span class="hljs-keyword">const</span> apiUrl = <span class="hljs-string">`http://localhost:11434/api/generate`</span>;
    <span class="hljs-keyword">const</span> body = {
        <span class="hljs-string">"model"</span>: <span class="hljs-string">"codellama"</span>,
        <span class="hljs-string">"prompt"</span>: prompt,
        <span class="hljs-string">"stream"</span>: <span class="hljs-literal">false</span>,
    };
    fetch(apiUrl, {
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(body),
    })
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (!response.ok) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network response was not ok'</span>);
        }
        <span class="hljs-keyword">return</span> response.text();
    })
    .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> jsonData = <span class="hljs-built_in">JSON</span>.parse(data);
        <span class="hljs-keyword">const</span> response = jsonData.response;
        <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"codeSuggestion"</span>).innerHTML = response;
    })
    .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error));
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By following these steps, you can successfully integrate Ollama with your Chrome Extension, overcoming CORS issues and enabling seamless API interactions. Always consider security implications when allowing cross-origin requests and only whitelist trusted sources.</p>
]]></content:encoded></item><item><title><![CDATA[How to Open Chrome Extension's Side Panel: A Comprehensive Guide]]></title><description><![CDATA[Chrome extensions can now utilize the chrome.sidePanel API to create additional user interface elements. This guide explains how to open a Chrome extension's side panel using a button click inside the popup or directly from the extension icon.
Soluti...]]></description><link>https://blog.mellowtel.com/how-to-open-chrome-extensions-side-panel-a-comprehensive-guide</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-open-chrome-extensions-side-panel-a-comprehensive-guide</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[mellowtel]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Mon, 23 Sep 2024 21:46:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727127933932/7be6b3ff-c90b-4fa7-918d-9eace0d918ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Chrome extensions can now utilize the <code>chrome.sidePanel</code> API to create additional user interface elements. This guide explains how to open a Chrome extension's side panel using a button click inside the popup or directly from the extension icon.</p>
<h2 id="heading-solution-1-opening-the-side-panel-on-action-click">Solution 1: Opening the Side Panel on Action Click</h2>
<p>To open the side panel when the user clicks the extension icon in the toolbar:</p>
<ol>
<li>Update your <code>manifest.json</code>:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"permissions"</span>: [<span class="hljs-string">"sidePanel"</span>],
  <span class="hljs-attr">"side_panel"</span>: {
    <span class="hljs-attr">"default_path"</span>: <span class="hljs-string">"sidepanel.html"</span>
  }
}
</code></pre>
<ol start="2">
<li>In your <code>service-worker.js</code>:</li>
</ol>
<pre><code class="lang-javascript">chrome.sidePanel
  .setPanelBehavior({ <span class="hljs-attr">openPanelOnActionClick</span>: <span class="hljs-literal">true</span> })
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(error));
</code></pre>
<h2 id="heading-solution-2-opening-the-side-panel-from-the-popup">Solution 2: Opening the Side Panel from the Popup</h2>
<p>To open the side panel when a user clicks a button inside the extension popup:</p>
<ol>
<li>Update your <code>manifest.json</code>:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"background"</span>: {
    <span class="hljs-attr">"service_worker"</span>: <span class="hljs-string">"service-worker.js"</span>
  },
  <span class="hljs-attr">"side_panel"</span>: {
    <span class="hljs-attr">"default_path"</span>: <span class="hljs-string">"sidepanel.html"</span>
  },
  <span class="hljs-attr">"action"</span>: {
    <span class="hljs-attr">"default_popup"</span>: <span class="hljs-string">"popup.html"</span>
  },
  <span class="hljs-attr">"permissions"</span>: [<span class="hljs-string">"sidePanel"</span>]
}
</code></pre>
<ol start="2">
<li>In your <code>popup.js</code>:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'openSidePanel'</span>).addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  chrome.runtime.sendMessage({<span class="hljs-attr">action</span>: <span class="hljs-string">'open_side_panel'</span>});
});
</code></pre>
<ol start="3">
<li>In your <code>service-worker.js</code>:</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> windowId;

chrome.tabs.onActivated.addListener(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">activeInfo</span>) </span>{
  windowId = activeInfo.windowId;
});

chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">message, sender</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (message.action === <span class="hljs-string">'open_side_panel'</span>) {
    chrome.sidePanel.open({ <span class="hljs-attr">windowId</span>: windowId });
  }
});
</code></pre>
<h2 id="heading-alternative-solution-direct-api-call">Alternative Solution: Direct API Call</h2>
<p>For a simpler approach, call <a target="_blank" href="http://chrome.sidePanel.open"><code>chrome.sidePanel.open</code></a><code>()</code> directly in your popup script:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleOpenSidePanel = <span class="hljs-function">() =&gt;</span> {
  chrome.windows.getCurrent({ <span class="hljs-attr">populate</span>: <span class="hljs-literal">true</span> }, <span class="hljs-function">(<span class="hljs-params"><span class="hljs-built_in">window</span></span>) =&gt;</span> {
    chrome.sidePanel.open({ <span class="hljs-attr">windowId</span>: <span class="hljs-built_in">window</span>.id });
  });
}
</code></pre>
<h2 id="heading-best-practices-and-tips">Best Practices and Tips</h2>
<ol>
<li><p>Include necessary permissions in your <code>manifest.json</code>.</p>
</li>
<li><p>Handle errors gracefully.</p>
</li>
<li><p>Use TypeScript for better type checking and autocomplete support.</p>
</li>
<li><p>Test your extension thoroughly in different scenarios.</p>
</li>
</ol>
<p>By implementing one of these solutions, you can successfully open your Chrome extension's side panel using a button click inside the popup or directly from the extension icon.</p>
]]></content:encoded></item><item><title><![CDATA[How to build a Chrome Extension with React]]></title><description><![CDATA[In this guide, I'll share how I built a color-changing extension using React and Plasmo, a framework that streamlines the development process.
Why React for Chrome Extensions?
React offers several advantages for extension development:

Familiar Terri...]]></description><link>https://blog.mellowtel.com/how-to-build-a-chrome-extension-with-react</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-build-a-chrome-extension-with-react</guid><category><![CDATA[React]]></category><category><![CDATA[Plasmo]]></category><category><![CDATA[chrome extension]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 22 Sep 2024 23:48:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727048867878/e96f2576-ecb1-4c90-b920-5dc8b92193cf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this guide, I'll share how I built a color-changing extension using React and Plasmo, a framework that streamlines the development process.</p>
<h2 id="heading-why-react-for-chrome-extensions">Why React for Chrome Extensions?</h2>
<p>React offers several advantages for extension development:</p>
<ol>
<li><p><strong>Familiar Territory</strong>: Leverage your existing React knowledge.</p>
</li>
<li><p><strong>Component-Based Architecture</strong>: Perfect for building modular extension UIs.</p>
</li>
<li><p><strong>Rich Ecosystem</strong>: Access to numerous React libraries and tools.</p>
</li>
<li><p><strong>Performance</strong>: React's virtual DOM optimizes extension performance.</p>
</li>
</ol>
<h2 id="heading-introducing-plasmo-simplifying-extension-development">Introducing Plasmo: Simplifying Extension Development</h2>
<p>Plasmo is a game-changer for React-based extension development:</p>
<ul>
<li><p><strong>React-First Approach</strong>: Seamless integration with React.</p>
</li>
<li><p><strong>Developer Experience</strong>: Features like hot reloading boost productivity.</p>
</li>
<li><p><strong>TypeScript Support</strong>: Built-in support for type-safe code.</p>
</li>
<li><p><strong>Manifest V3 Compatibility</strong>: Handles Chrome's latest manifest version complexities.</p>
</li>
</ul>
<h2 id="heading-building-the-extension-a-step-by-step-guide">Building the Extension: A Step-by-Step Guide</h2>
<p>Let's create a simple extension that changes the background color of web pages.</p>
<h3 id="heading-step-1-setting-up-the-project">Step 1: Setting Up the Project</h3>
<p>Ensure you have Node.js installed, then run:</p>
<pre><code class="lang-bash">npm create plasmo@latest
</code></pre>
<p>Follow the prompts, selecting React as your framework.</p>
<h3 id="heading-step-2-understanding-the-project-structure">Step 2: Understanding the Project Structure</h3>
<p>After initialization, your project structure will look like this:</p>
<pre><code class="lang-plaintext">color-shifter/
├── popup.tsx
├── style.css
└── package.json
</code></pre>
<p><code>popup.tsx</code> is the entry point for your extension's popup UI.</p>
<h3 id="heading-step-3-crafting-the-popup-component-and-styles">Step 3: Crafting the Popup Component and Styles</h3>
<p>First, create a new file called <code>style.css</code> in your project's root directory. Then, add some basic styling to it:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.popup-container</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
}

<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span> <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#4CAF50</span>;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>Next, create your popup component in <code>popup.tsx</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./style.css"</span>

<span class="hljs-keyword">const</span> Popup = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>)

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"popup-container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Color Shifter<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Change the web's colors with a click!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount(count + 1)}&gt;
        Clicked {count} times
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Popup
</code></pre>
<p>Make sure to import the <code>style.css</code> file at the top of your <code>popup.tsx</code> as shown above. This will apply the styles to your popup component.</p>
<h3 id="heading-step-4-adding-color-changing-functionality">Step 4: Adding Color-Changing Functionality</h3>
<p>Enhance the popup component with color-changing functionality:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./style.css"</span>

<span class="hljs-keyword">const</span> Popup = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [color, setColor] = useState(<span class="hljs-string">"#ffffff"</span>)

  <span class="hljs-keyword">const</span> changeColor = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> newColor = <span class="hljs-string">`#<span class="hljs-subst">${<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random()*<span class="hljs-number">16777215</span>).toString(<span class="hljs-number">16</span>)}</span>`</span>
    setColor(newColor)
    chrome.tabs.query({<span class="hljs-attr">active</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">currentWindow</span>: <span class="hljs-literal">true</span>}, <span class="hljs-function">(<span class="hljs-params">tabs</span>) =&gt;</span> {
      chrome.tabs.sendMessage(tabs[<span class="hljs-number">0</span>].id, {<span class="hljs-attr">type</span>: <span class="hljs-string">"COLOR_CHANGE"</span>, <span class="hljs-attr">color</span>: newColor})
    })
  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Initialize color when popup opens</span>
    chrome.tabs.query({<span class="hljs-attr">active</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">currentWindow</span>: <span class="hljs-literal">true</span>}, <span class="hljs-function">(<span class="hljs-params">tabs</span>) =&gt;</span> {
      chrome.tabs.sendMessage(tabs[<span class="hljs-number">0</span>].id, {<span class="hljs-attr">type</span>: <span class="hljs-string">"GET_COLOR"</span>}, <span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (response &amp;&amp; response.color) {
          setColor(response.color)
        }
      })
    })
  }, [])

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"popup-container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Color Shifter<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"color-preview"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{backgroundColor:</span> <span class="hljs-attr">color</span>}}&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{changeColor}</span>&gt;</span>Shift Colors!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Current color: {color}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Popup
</code></pre>
<h3 id="heading-step-5-creating-a-content-script">Step 5: Creating a Content Script</h3>
<p>Create a new file <code>content.ts</code> in the root directory to apply the color change to webpages:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">let</span> currentColor = <span class="hljs-string">"#ffffff"</span>

chrome.runtime.onMessage.addListener(<span class="hljs-function">(<span class="hljs-params">request, sender, sendResponse</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (request.type === <span class="hljs-string">"COLOR_CHANGE"</span>) {
    currentColor = request.color
    <span class="hljs-built_in">document</span>.body.style.backgroundColor = currentColor
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (request.type === <span class="hljs-string">"GET_COLOR"</span>) {
    sendResponse({color: currentColor})
  }
})
</code></pre>
<h3 id="heading-step-6-development-and-testing">Step 6: Development and Testing</h3>
<p>To develop your extension with hot reloading, run:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>This will start Plasmo's development server, allowing you to see changes in real-time.</p>
<p>To test your extension:</p>
<ol>
<li><p>Open Chrome and go to <code>chrome://extensions</code></p>
</li>
<li><p>Enable "Developer mode"</p>
</li>
<li><p>Click "Load unpacked"</p>
</li>
<li><p>Navigate to your project's <code>build</code> folder, then select the <code>chrome-mv3-dev</code> folder inside it</p>
</li>
</ol>
<p>Your color-shifting extension should now appear in Chrome's toolbar.</p>
<h2 id="heading-lessons-learned-and-tips">Lessons Learned and Tips</h2>
<ol>
<li><p><strong>Start Simple</strong>: Begin with basic functionality and build up gradually.</p>
</li>
<li><p><strong>Use React Hooks</strong>: Leverage hooks like <code>useState</code> and <code>useEffect</code> for state management and side effects.</p>
</li>
<li><p><strong>Leverage Chrome APIs</strong>: Familiarize yourself with Chrome's extension APIs.</p>
</li>
<li><p><strong>Debug Effectively</strong>: Use Chrome's developer tools, especially the "Inspect views" option for your extension.</p>
</li>
<li><p><strong>Consider Performance</strong>: Keep your extension lightweight and efficient.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building a Chrome extension with React and Plasmo opens up new possibilities for developers. Whether you're creating a simple utility or a complex tool, this approach provides a solid foundation.</p>
<p>As you build, always keep your end-users in mind. The best extensions solve real problems and provide value. Happy coding, and may your extensions enhance the browsing experience for users worldwide!</p>
<hr />
<p>If you found this guide helpful, consider sharing it with fellow developers. For more advanced topics, check out the official Plasmo and Chrome Extension documentation.</p>
]]></content:encoded></item><item><title><![CDATA[Essential Browser Plugins for Enhanced Web Browsing]]></title><description><![CDATA[Feeling frustrated with a sluggish, clunky browsing experience?
You're not alone. These days, our online lives are busier than ever. And with so much content to sift through, it's a real challenge to keep things streamlined and productive.
That's whe...]]></description><link>https://blog.mellowtel.com/essential-browser-plugins-for-enhanced-web-browsing</link><guid isPermaLink="true">https://blog.mellowtel.com/essential-browser-plugins-for-enhanced-web-browsing</guid><category><![CDATA[browser plugins]]></category><category><![CDATA[Browsers]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sun, 22 Sep 2024 22:51:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727045346048/3d2b59e8-8275-4091-9b98-aaf405ed4a25.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Feeling frustrated with a sluggish, clunky browsing experience?</p>
<p>You're not alone. These days, our online lives are busier than ever. And with so much content to sift through, it's a real challenge to keep things streamlined and productive.</p>
<p>That's where browser plugins come in. These tools can make a world of difference, helping you browse faster, stay organized, and generally get more done.</p>
<p>In this article, I'll share some of my favorite must-have browser plugins. Whether you're a Chrome, Firefox, or Edge fan, you'll find plenty of useful options to level up your web experience.</p>
<h2 id="heading-boost-your-productivity-with-these-essential-plug-ins">Boost Your Productivity with These Essential Plug-ins</h2>
<h3 id="heading-1-ublock-originhttpsublockorigincom-the-ultimate-ad-blocker">1. <a target="_blank" href="https://ublockorigin.com/"><strong>uBlock Origin</strong></a> - The Ultimate Ad Blocker</h3>
<p>Look, ads are a necessary evil on the internet. But that doesn't mean you have to put up with the constant bombardment of pop-ups, video ads, and other intrusive nonsense.</p>
<p>uBlock Origin is hands down the best ad blocker out there. It's lightweight, lightning-fast, and incredibly effective at blocking all kinds of unwanted content. Say goodbye to frustrating ad overload and hello to a clean, distraction-free browsing experience.</p>
<h3 id="heading-2-grammarlyhttpswwwgrammarlycom-your-personal-writing-assistant">2. <a target="_blank" href="https://www.grammarly.com/"><strong>Grammarly</strong></a> - Your Personal Writing Assistant</h3>
<p>Whether you're dashing off emails, posting on social media, or working on a big project, good grammar and clear writing are essential. But let's be real - we all make mistakes sometimes.</p>
<p>That's where Grammarly comes in. This smart little plug-in watches your back, flagging errors and offering suggestions to help you communicate more effectively. It's like having a personal editor on call 24/7.</p>
<h3 id="heading-3-lastpasshttpswwwlastpasscom-secure-password-management-made-easy">3. <a target="_blank" href="https://www.lastpass.com/"><strong>LastPass</strong></a> - Secure Password Management Made Easy</h3>
<p>In our increasingly digital world, juggling multiple passwords is a major headache. LastPass takes the pain out of password management, storing all your login credentials securely in one convenient place.</p>
<p>With LastPass, you can generate strong, unique passwords for all your accounts and access them with just a single master password. It's a game-changer for anyone who's tired of constantly resetting forgotten passwords.</p>
<h3 id="heading-4-honeyhttpswwwjoinhoneycom-effortless-coupon-finding">4. <a target="_blank" href="https://www.joinhoney.com/"><strong>Honey</strong></a> - Effortless Coupon-Finding</h3>
<p>Who doesn't love a good deal? Honey is a must-have plug-in for savvy online shoppers. With just a click, it scours the internet for valid coupon codes and automatically applies the best ones at checkout.</p>
<p>No more scouring the web for promo codes or missing out on potential savings. Honey does all the hard work for you, helping you squeeze the most value out of every online purchase.</p>
<h3 id="heading-5-notion-web-clipperhttpswwwnotionsoweb-clipper-organize-your-online-research">5. <a target="_blank" href="https://www.notion.so/web-clipper"><strong>Notion Web Clipper</strong></a> - Organize Your Online Research</h3>
<p>If you're like me, you're constantly stumbling upon fascinating articles, helpful how-to guides, and other web content you want to save for later. But without a reliable system, it's easy for all those bookmarks and notes to get lost in the shuffle.</p>
<p>That's why I love the Notion Web Clipper. With a single click, you can instantly save web pages, screenshots, and more directly to your Notion workspace. It's a game-changer for keeping your online research organized and at your fingertips.</p>
<h2 id="heading-bonus-plug-ins-to-consider">Bonus Plug-ins to Consider</h2>
<p>Those are my top five must-have browser plug-ins, but the options don't end there. Here are a few other handy tools worth checking out:</p>
<ul>
<li><p><a target="_blank" href="https://momentumdash.com/"><strong>Momentum</strong></a> - Turns your new tab page into a personal dashboard with to-do lists, weather updates, and motivational quotes.</p>
</li>
<li><p><a target="_blank" href="https://darkreader.org/"><strong>Dark Reader</strong></a> - Automatically applies a sleek dark mode to any website, reducing eye strain.</p>
</li>
<li><p><a target="_blank" href="https://www.octotree.io/"><strong>Octotree</strong></a> - Adds a sidebar that makes navigating GitHub repos a breeze.</p>
</li>
<li><p><a target="_blank" href="https://www.reddit.com/r/Imagus/"><strong>Imagus</strong></a> - Lets you preview images, videos, and other content by simply hovering over links.</p>
</li>
<li><p><a target="_blank" href="https://markuphero.com/"><strong>Markup Hero</strong></a> - Allows you to annotate, highlight, and edit web pages and screenshots.</p>
</li>
</ul>
<h2 id="heading-faqs">FAQs</h2>
<p><strong>What are the benefits of using browser plug-ins?</strong> Browser plug-ins can help you:</p>
<ul>
<li><p>Boost productivity and efficiency by automating tasks</p>
</li>
<li><p>Enhance security and protect your online privacy</p>
</li>
<li><p>Simplify content organization and research</p>
</li>
<li><p>Save money through features like coupon finders</p>
</li>
<li><p>Personalize and optimize your browsing experience</p>
</li>
</ul>
<p><strong>Do browser plug-ins slow down my computer?</strong> A well-designed, lightweight plug-in shouldn't significantly impact your computer's performance. In fact, many plug-ins can actually speed things up by blocking ads, managing passwords, and reducing distractions. Just be cautious of installing too many plug-ins, as that could potentially cause issues.</p>
<p><strong>Are browser plug-ins safe to use?</strong> When it comes to browser plug-ins, safety is always a top concern. The best approach is to stick with reputable, well-reviewed options from trusted developers. Avoid sketchy, unknown plug-ins that could pose security risks. Also, be sure to keep your plug-ins updated to ensure you're protected against the latest threats.</p>
<p><strong>Can I use the same plug-ins across different browsers?</strong> The short answer is: it depends. Many popular plug-ins, like the ones I mentioned, are available for multiple browsers (Chrome, Firefox, Edge, etc.). However, some plug-ins are browser-specific. Before installing a plug-in, make sure it's compatible with the browser you're using.</p>
]]></content:encoded></item><item><title><![CDATA[How to monetize your Chrome extension]]></title><description><![CDATA[In this guide, we'll explore effective strategies to monetize Chrome extensions. It's simpler than you might think.
Freemium: The Trial Run
• Provide a basic version at no cost
• Offer premium features for a fee
• Consider various pricing plans
Examp...]]></description><link>https://blog.mellowtel.com/how-to-monetize-your-chrome-extension-a-practical-guide</link><guid isPermaLink="true">https://blog.mellowtel.com/how-to-monetize-your-chrome-extension-a-practical-guide</guid><category><![CDATA[chrome extension]]></category><category><![CDATA[Monetization]]></category><category><![CDATA[mellowtel]]></category><category><![CDATA[Browser Extension]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sat, 21 Sep 2024 23:16:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726960496592/1baf5adf-0277-4ac6-9519-6bc383870929.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this guide, we'll explore effective strategies to monetize Chrome extensions. It's simpler than you might think.</p>
<h3 id="heading-freemium-the-trial-run">Freemium: The Trial Run</h3>
<p>• Provide a basic version at no cost</p>
<p>• Offer premium features for a fee</p>
<p>• Consider various pricing plans</p>
<p>Example: <a target="_blank" href="https://www.grammarly.com/">Grammarly</a> offers free basic grammar checks and paid advanced writing suggestions.</p>
<h3 id="heading-subscription-ongoing-value">Subscription: Ongoing Value</h3>
<p>• Provides steady income</p>
<p>• Encourages continual updates</p>
<p>• Often more appealing than one-time large payments</p>
<p>Example: <a target="_blank" href="https://www.lastpass.com/">LastPass</a> uses this model, offering basic features for free and advanced security options for subscribers.</p>
<h3 id="heading-mellowtel-innovative-resource-sharing">Mellowtel: Innovative Resource Sharing</h3>
<p>• Users opt-in to share unused internet bandwidth</p>
<p>• AI companies use the shared network for model training</p>
<p>• You earn based on bandwidth usage</p>
<p>• Non-intrusive and privacy-focused</p>
<p>Example: <a target="_blank" href="https://www.mellowtel.com">Mellowtel</a> is pioneering this approach for extensions with a large, active user base.</p>
<h3 id="heading-in-app-purchases-customized-experience">In-App Purchases: Customized Experience</h3>
<p>• Flexible for different user needs</p>
<p>• Caters to varying budgets</p>
<p>• Can increase overall revenue</p>
<p>Example: <a target="_blank" href="https://evernote.com/features/webclipper">Evernote Web Clipper</a> offers premium clipping features as in-app purchases.</p>
<h3 id="heading-ads-and-sponsorships-finding-the-right-balance">Ads and Sponsorships: Finding the Right Balance</h3>
<p>• Choose relevant advertisements</p>
<p>• Seek out compatible brand partnerships</p>
<p>• Avoid overwhelming users with too many ads</p>
<p>Example: <a target="_blank" href="https://www.wikiwand.com/">Wikiwand</a> displays unobtrusive ads on its redesigned Wikipedia pages.</p>
<h2 id="heading-advanced-monetization-techniques">Advanced Monetization Techniques</h2>
<h3 id="heading-affiliate-marketing-mutually-beneficial-recommendations">Affiliate Marketing: Mutually Beneficial Recommendations</h3>
<p>• Include links to relevant products</p>
<p>• Earn commissions on resulting sales</p>
<p>• Works well if your extension aids purchasing decisions</p>
<p>Example: <a target="_blank" href="https://www.rakuten.com/">Rakuten</a> (formerly Ebates) extension earns through affiliate commissions when users make purchases.</p>
<h3 id="heading-selling-to-businesses-the-bigger-picture">Selling to Businesses: The Bigger Picture</h3>
<p>• Businesses may want to acquire or license your extension</p>
<p>• Can result in significant financial gains</p>
<p>• Might open doors to new opportunities</p>
<p>Example: <a target="_blank" href="https://www.boomeranggmail.com/">Boomerang for Gmail</a> was acquired by Baydin, expanding its reach and capabilities.</p>
<h3 id="heading-premium-support-enhanced-assistance">Premium Support: Enhanced Assistance</h3>
<p>• Offer tiered support levels</p>
<p>• Charge for priority assistance or additional features</p>
<p>• Appeals to users who need more comprehensive support</p>
<p>Example: <a target="_blank" href="https://www.ghostery.com/">Ghostery</a> offers premium support and configuration services for its privacy-focused extension.</p>
<h2 id="heading-common-challenges-and-solutions">Common Challenges and Solutions</h2>
<p>When monetizing your Chrome extension, you may encounter some challenges. Here are common issues and how to address them:</p>
<h3 id="heading-users-reluctant-to-pay-for-previously-free-features">Users reluctant to pay for previously free features</h3>
<p>Solutions:</p>
<p>• Clearly demonstrate the value of premium offerings</p>
<p>• Provide a trial period for premium features</p>
<h3 id="heading-disruptive-ads">Disruptive ads</h3>
<p>Solutions:</p>
<p>• Ensure ads are relevant and unobtrusive</p>
<p>• Prioritize user experience alongside monetization</p>
<h3 id="heading-compliance-with-chrome-web-store-guidelines">Compliance with Chrome Web Store guidelines</h3>
<p>Solutions:</p>
<p>• Stay informed about Chrome Web Store policies</p>
<p>• Consider approved monetization methods like Mellowtel</p>
<h3 id="heading-competing-with-free-alternatives">Competing with free alternatives</h3>
<p>Solutions:</p>
<p>• Highlight unique features of your extension</p>
<p>• Ensure a superior user experience</p>
<h2 id="heading-faqs">FAQs</h2>
<p><strong>What's a realistic income expectation from a Chrome extension?</strong></p>
<p>It varies widely. Some developers earn modest amounts, while others generate substantial income. Your niche, user base, and monetization approach all play a role.</p>
<p>With Mellowtel, an extension that has 1000 active users can expect $50 monthly.</p>
<p><strong>Will monetization negatively impact my user base?</strong></p>
<p>Not if done thoughtfully. Be open about changes, ensure value, and avoid excessive monetization. Users often understand fair compensation for valuable tools.</p>
<p><strong>Is Mellowtel secure for users?</strong></p>
<p>Yes, it prioritizes user safety. It's opt-in, transparent, and doesn't access personal information. It simply utilizes spare bandwidth.</p>
<p><strong>Can I combine different monetization methods?</strong></p>
<p>Absolutely. Many successful extensions use multiple strategies. Just ensure it remains clear and straightforward for users.</p>
<h2 id="heading-useful-links">Useful Links</h2>
<p>• <a target="_blank" href="https://www.mellowtel.it">Mellowtel Official Website</a></p>
<p>• <a target="_blank" href="https://www.mellowtel.it/about-mellowtel/">About Mellowtel</a></p>
<p>• <a target="_blank" href="https://github.com/mellowtel-inc/mellowtel-js">Mellowtel GitHub Repository</a></p>
<p>Remember, the key to successfully monetizing your Chrome extension is to provide value to your users while finding a balance between generating revenue and maintaining a positive user experience. Whether you choose traditional methods or innovative approaches like Mellowtel, always prioritize your users' needs and preferences.</p>
]]></content:encoded></item><item><title><![CDATA[Mellowtel: Sharing Bandwidth Safely and Securely]]></title><description><![CDATA[At Mellowtel, we've created a service that lets you share your unused internet bandwidth. But you might be wondering: "Is it safe? What about my privacy?" Let's break it down in simple terms:
1. You're Anonymous
We assign you a random identifier that...]]></description><link>https://blog.mellowtel.com/mellowtel-sharing-bandwidth-safely-and-securely</link><guid isPermaLink="true">https://blog.mellowtel.com/mellowtel-sharing-bandwidth-safely-and-securely</guid><category><![CDATA[mellowtel]]></category><category><![CDATA[privacy]]></category><dc:creator><![CDATA[Mellowtel]]></dc:creator><pubDate>Sat, 21 Sep 2024 21:42:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726954843402/1247174e-8f4c-4a6a-b2b5-06a7550bd2ee.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>At Mellowtel, we've created a service that lets you share your unused internet bandwidth. But you might be wondering: "Is it safe? What about my privacy?" Let's break it down in simple terms:</p>
<h2 id="heading-1-youre-anonymous">1. You're Anonymous</h2>
<p>We assign you a random identifier that doesn't connect to your real identity. This ensures your privacy while using our service.</p>
<h2 id="heading-2-we-collect-almost-nothing">2. We Collect Almost Nothing</h2>
<p>We're like minimalists - we only keep what we absolutely need. Here's what we do collect:</p>
<ul>
<li><p>A random ID number</p>
</li>
<li><p>Whether you're participating or not</p>
</li>
<li><p>How much internet you're sharing</p>
</li>
<li><p>Your IP address</p>
</li>
</ul>
<h3 id="heading-why-we-need-your-ip-address">Why We Need Your IP Address</h3>
<p>An IP address is like your home's street address, but for the internet. We need to know this to make our service work, just like a delivery person needs your address to bring you a package.</p>
<p>Here's why it's okay:</p>
<ol>
<li><p>It's Necessary: Without your IP address, we couldn't route internet traffic through your connection. It's essential for the basic function of our service.</p>
</li>
<li><p>It's Not Personal: An IP address doesn't tell us who you are, your name, or any other personal details.</p>
</li>
<li><p>It's Protected: We treat your IP address with the same care as all your other data. We don't sell it or share it with others.</p>
</li>
<li><p>It's Temporary: IP addresses can change, especially if you restart your router or your internet provider assigns you a new one.</p>
</li>
<li><p>It's Like a Postal Code: It gives a general idea of your location (like a city), but not your exact address.</p>
</li>
</ol>
<p>Think of it this way: We're like a friendly neighbor who borrows your garden hose. We need to know which house to go to (your IP), but we don't need or want to know anything else about you.</p>
<h2 id="heading-3-we-follow-the-rules">3. We Follow the Rules</h2>
<p>There are laws about how companies should handle your data (like GDPR). We follow these rules, which means we're committed to protecting your rights and keeping your information safe.</p>
<h2 id="heading-4-nothing-to-hide">4. Nothing to Hide</h2>
<p>Our code is open-source. It's like we're cooking in a kitchen with glass walls - anyone can look in and see what we're doing. This openness helps build trust because there are no secrets about how we handle your data.</p>
<h2 id="heading-5-super-safe-browsing">5. Super-Safe Browsing</h2>
<p>When we use your shared internet, it's like using a secret passage. We use an "incognito" mode, so no one can see where the internet traffic has been. No history, no cookies, no breadcrumbs left behind.</p>
<h2 id="heading-6-rigorous-partner-vetting">6. Rigorous Partner Vetting</h2>
<p>We take extra steps to ensure that only trustworthy companies can use our service:</p>
<ol>
<li><p><strong>Thorough Screening</strong>: Every company goes through a comprehensive vetting process before being allowed to use Mellowtel. This includes a personal call with our team to understand the company's intentions and use cases.</p>
</li>
<li><p><strong>Trusted Partners</strong>: Most companies using Mellowtel are Y Combinator startups, adding an extra layer of credibility and accountability.</p>
</li>
<li><p><strong>Continuous Monitoring</strong>: We log and monitor all URLs being accessed through our service. This allows us to keep a vigilant eye on how companies are using the shared bandwidth.</p>
</li>
<li><p><strong>Proactive Filtering</strong>: We're implementing a sophisticated filter endpoint with a blacklist of URLs we don't want to send. Any requests to these URLs are simply ignored, adding an extra layer of protection.</p>
</li>
<li><p><strong>Developer Empowerment</strong>: In the future, developers will have the ability to add to this blacklist, giving them control over which URLs they don't want sent to their users.</p>
</li>
</ol>
<h2 id="heading-7-commitment-to-ethical-operations">7. Commitment to Ethical Operations</h2>
<p>We've built Mellowtel on a foundation of trust and ethical practices:</p>
<ol>
<li><p><strong>Clear Terms of Service</strong>: All companies using Mellowtel must agree to our comprehensive Terms of Service, which explicitly outline acceptable use of the platform.</p>
</li>
<li><p><strong>Trust-Based Relationships</strong>: We foster close working relationships with our partners, ensuring alignment with our values and commitment to user protection.</p>
</li>
<li><p><strong>Proactive Measures</strong>: Our focus is on prevention and responsible use through careful partner selection, ongoing monitoring, and automated protections.</p>
</li>
<li><p><strong>Continuous Improvement</strong>: Our team is constantly enhancing our security measures and ethical safeguards, staying ahead of potential threats to protect users and maintain service integrity.</p>
</li>
<li><p><strong>Legal Preparedness</strong>: While we've built our service on trust and have never had to use it, we maintain the ability to take legal action against any severe violations as an additional deterrent against misuse.</p>
</li>
</ol>
<h2 id="heading-8-proven-track-record">8. Proven Track Record</h2>
<p>In the six months since launch, we've maintained a perfect record with zero instances of abuse. This achievement validates our rigorous vetting process and ongoing monitoring. Given our careful partner selection and robust safeguards, we don't anticipate any abuse occurring in the future. Our commitment to security and ethical operations continues to be the cornerstone of our service.</p>
<h2 id="heading-want-to-learn-more">Want to Learn More?</h2>
<p>If you're interested in digging deeper into our privacy and security practices, here are some helpful links:</p>
<ol>
<li><p><a target="_blank" href="https://mellowtel.com"><strong>Our Official Website</strong></a> - Get the latest information straight from the source.</p>
</li>
<li><p><a target="_blank" href="https://www.mellowtel.com/mellowtel-privacy-policy/"><strong>Our Privacy Policy</strong></a> - For a detailed explanation of how we handle your data.</p>
</li>
<li><p><a target="_blank" href="https://github.com/mellowtel-inc/mellowtel-js"><strong>Our GitHub Repository</strong></a> - See our open-source code for yourself.</p>
</li>
<li><p><a target="_blank" href="https://docs.mellowtel.it/get-started/welcome"><strong>Our Documentation</strong></a> - Learn more about how Mellowtel works.</p>
</li>
<li><p><a target="_blank" href="https://docs.mellowtel.it/concepts/privacy"><strong>Privacy Concepts at Mellowtel</strong></a> - A deeper dive into our privacy approach.</p>
</li>
</ol>
]]></content:encoded></item></channel></rss>