Webfuse - The web augmentation platform | Product Hunt
Ideas
8
min read

Creating a Reader Mode Extension: A Web Augmentation Approach

Web browser extensions often come with installation barriers that limit user reach. Webfuse changes that by allowing developers to create shareable, install-free web augmentations. In this guide, you’ll build a lightweight Reader Mode using Mozilla’s Readability.js and deploy it via Webfuse. From writing a manifest and content script to setting up a Webfuse Space and sharing activation links, you'll learn how to empower users to toggle between standard and simplified views on any website—effortlessly and instantly.

Browser extensions require installation by every user and limit their reach. Webfuse, a web augmentation platform, changes this by allowing developers to create augmentations for any website that can be shared via a simple link. This means end-users experience the enhanced website directly, without needing to install any software themselves.

This guide will walk you through creating a lightweight Webfuse custom extension, Reader Mode using Mozilla's Readability.js. You'll learn how to configure your Webfuse Space and enable it across various third-party sites, such as news platforms and blogs.

What You'll Need to Get Started

Before diving into the creation process, make sure you have the following:

  • A Webfuse account. If you don't have one, you can sign up at webfuse.com.
  • A code editor, such as VS Code, Sublime Text, or any editor of your choice, for creating the extension files.

If you've worked with browser extensions before, creating Webfuse custom extensions will feel very similar. They follow a familiar structure, using a manifest.json file to define the extension and content scripts (like content.js) to interact with web pages. This approach makes it easy to add new features or modify websites within a Webfuse session. You can find more details in the official Webfuse documentation.

Step 1: Building the Reader Mode Extension

Our first step is to create the core logic for our Reader Mode. This involves using Mozilla's Readability.js library to extract the primary content from an article and display it in a simplified, clean view.

This extension will consist of two main files: a manifest.json file to describe the extension and a main.js file containing the operational JavaScript code.

On your computer, create a new folder named reader-mode-extension. Inside this folder, create manifest.json file.

This file tells Webfuse about your extension, its permissions, and how it should run.

{
  "manifest_version": 3,
  "name": "Reader Mode",
  "version": "1.0.0",
  "description": "Simplifies web pages for easier reading",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["main.js"],
      "run_at": "document_end"
    }
  ],
  "host_permissions": ["<all_urls>"]
}

Add a file called main.js.

This script contains the functionality for the reader mode. It dynamically loads Readability.js, adds a toggle button to the page, and includes functions to switch between the original page view and the simplified reader view.

// Dynamically load Readability.js if not already present
if (typeof Readability === "undefined") {
  const script = document.createElement("script");
  script.src = "https://unpkg.com/@mozilla/readability@0.4.4/Readability.js";
  script.onload = () => console.log("Readability.js loaded.");
  document.head.appendChild(script);
}

// UI SETUP: Create and style the Reader Mode Toggle Button
const toggleWrapper = document.createElement("div");
toggleWrapper.id = "reader-mode-toggle-wrapper";
Object.assign(toggleWrapper.style, {
  position: "fixed",
  top: "250px",
  right: "20px",
  zIndex: "9999",
});

const toggleButton = document.createElement("button");
toggleButton.textContent = "📰 Reader Mode";
Object.assign(toggleButton.style, {
  padding: "8px 12px",
  background: "#111",
  color: "#fff",
  border: "none",
  borderRadius: "5px",
  cursor: "pointer",
  fontSize: "14px",
  boxShadow: "0 2px 6px rgba(0,0,0,0.2)",
});

toggleWrapper.appendChild(toggleButton);
document.body.appendChild(toggleWrapper);

// STATE VARIABLES
let readerModeEnabled = false;
let originalBodyHTML = document.body.innerHTML; // Store original page content

// FUNCTION: removeAdBlocks
// Description: Removes common ad elements from the DOM to clean up the view before parsing.
function removeAdBlocks() {
  document.querySelectorAll('[id*="ad-"], [class*="ad-"], [class*="adsninja"], [class*="adzone"]').forEach(el => el.remove());
  document.querySelectorAll('.ad-zone-container, .ad-zone, .ad-loading, .an-zone-tag-top, .an-zone-tag-bottom, .dynamically-injected-refresh-ad-zone').forEach(el => el.remove());
  document.querySelectorAll('iframe, script').forEach(el => {
    const src = el.src || '';
    if (src.includes('ads') || src.includes('doubleclick') || src.includes('googletag')) {
      el.remove();
    }
  });
}

// FUNCTION: enableReaderMode
// Description: Parses readable content using Readability.js and replaces the page content.
function enableReaderMode() {
  if (typeof Readability === "undefined") {
    alert("Readability.js not loaded yet. Please wait a few seconds and try again.");
    return;
  }

  originalBodyHTML = document.body.innerHTML; // Save current state before modifying
  removeAdBlocks(); // Attempt to remove ads for cleaner parsing

  const documentClone = document.cloneNode(true); // Clone the document for Readability
  const article = new Readability(documentClone).parse();

  if (!article || !article.content) {
    alert("Failed to extract readable content from this page.");
    // Restore original body if reader mode fails
    document.body.innerHTML = originalBodyHTML;
    document.body.appendChild(toggleWrapper); // Re-append toggle button
    return;
  }

  const readerHTML = `
    <div id="reader-mode-container" style="padding: 2rem; font-family: Georgia, serif; max-width: 800px; margin: auto; line-height: 1.6; font-size: 1.2rem; color: #222;">
      <h1>${article.title}</h1>
      ${article.content}
    </div>
  `;
  document.body.innerHTML = readerHTML;
  document.body.appendChild(toggleWrapper); // Ensure toggle button is visible in reader mode
}

// FUNCTION: disableReaderMode
// Description: Restores the original page content.
function disableReaderMode() {
  document.body.innerHTML = originalBodyHTML;
  document.body.appendChild(toggleWrapper); // Re-append toggle button
}

// EVENT HANDLER: Toggle Button Click
// Description: Enables or disables reader mode based on its current state.
toggleButton.addEventListener("click", () => {
  if (!readerModeEnabled) {
    enableReaderMode();
    toggleButton.textContent = "❌ Exit Reader Mode";
  } else {
    disableReaderMode();
    toggleButton.textContent = "📰 Reader Mode";
  }
  readerModeEnabled = !readerModeEnabled;
});

Step 2: Setting Up Your Webfuse Space and Installing the Extension

With the extension files ready, the next step is to configure a Webfuse "Space." A Space in Webfuse is essentially a container that points to an origin URL (the website to be augmented) and holds the configurations, including any custom extensions you want to apply.

  1. Navigate to your Webfuse Studio at webfuse.com/studio/ and log in or sign up if you haven't already.
  1. Create a new "Solo" Space. You can name it simply "Reader Mode."
  1. Click “Open Space”.
  1. Once your Space is created and you've opened it, locate and click on the Settings panel (often represented by a gear icon). From there, select Extensions.
  1. You will be presented with an option to upload your extension. Choose to use Webfuse Default Storage (or your configured storage if you have a custom setup). Click the upload button and select the entire reader-mode-extension folder you created in Step 1.
  1. After the upload is complete, you can click View files to verify that your manifest.json and main.js files are correctly uploaded within the folder.

Your Reader Mode extension is now installed in this Webfuse Space. This means that any website accessed through a Webfuse link associated with this Space will have your Reader Mode extension silently loaded and active.

Step 3: Activating Reader Mode with Webfuse Links

The real power of Webfuse shines in how you share these augmented experiences. To use your newly created Reader Mode on any website, you'll construct a special Webfuse link.

The general format for such a link is:
https://[your-webfuse-domain]/+[your-space-slug]/?url=[target-website-url]

For example, if your Webfuse Space slug (often derived from the name you gave it, e.g., "reader-mode") is reader-mode, and you want to apply it to a New York Times article, the link would look like this:

https://webfuse.com/+reader-mode/?url=https://www.nytimes.com/some-article-path

When someone clicks this link:

  • Webfuse initiates a virtual web session.
  • The target website (e.g., nytimes.com) is loaded within this session.
  • Your "Reader Mode" custom extension is automatically injected into the page.
  • The original site layout appears as usual, but your "📰 Reader Mode" toggle button will be visible (as defined in main.js).
  • The user can then click this toggle button to activate or deactivate the simplified reader view at their convenience.

You can try this on various news sites or blogs. For instance:

  • https://webfuse.com/+reader-mode/?url=https://www.bbc.com/news
  • https://webfuse.com/+reader-mode/?url=https://www.cnn.com
    (Remember to replace reader-mode with your actual Space slug if it's different.)

This user-controlled approach ensures that the original site's interactivity is preserved until the reader explicitly chooses the simplified view.

Step 4: Verifying Your Creation

It's time to test your Webfuse-powered Reader Mode. Open one of the Webfuse links you constructed in the previous step in your browser.

Here's what you should observe to confirm it's working correctly:

  1. The target website loads normally within the browser, but the URL will be your Webfuse domain.
  2. Your "📰 Reader Mode" toggle button should be visible on the page, typically positioned on the right side as styled in the main.js file.
  3. When you click the "📰 Reader Mode" button:
    • The script should attempt to extract the main content of the article using Readability.js.
    • The page should re-render, displaying only the article's title and body content in a clean, simplified layout.
    • Distracting elements like advertisements, sidebars, pop-ups, and comment sections should be removed.
    • The styling should change to the clean, readable format defined in your readerHTML string.
  4. Clicking the button again (which should now read "❌ Exit Reader Mode") should restore the page to its original layout.

If you encounter issues, such as Readability.js failing to parse the content, ensure the target page is indeed an article-like page. Readability.js works best on pages with clear article structures. You can also check the browser's developer console for any error messages originating from your main.js script or Readability.js.

Conclusion

You have successfully built and deployed a user-controlled Reader Mode extension using Webfuse. This tool enhances the reading experience on virtually any website by stripping away distractions, and importantly, it does so without requiring any end-user installations or modifications to the original website's code.

This project highlights several key advantages of Webfuse:

  • No Installation Friction: Users simply click a link to get the enhanced experience.
  • Modify Any Site: You can augment third-party websites you don't own.
  • Centralized Control: As the creator, you define and manage the augmentation, ensuring a consistent experience for all users of your Webfuse link.
  • Custom JavaScript: You can leverage familiar web technologies (HTML, CSS, JavaScript) and libraries like Readability.js to build powerful custom extensions.

With Webfuse, the browser becomes a more flexible and controllable environment. You can create tailored web experiences, from simple UI tweaks like this Reader Mode to sophisticated workflow automations and collaborative tools, all shareable through the simplicity of a URL. This opens up numerous possibilities for enhancing web interaction for yourself and others.

Extend the web instantly

Try webfuse for yourself!