The Tech Stack Behind Web Highlights: A Chrome Extension with Over 10,000 Weekly Users

Discover the technology stack behind Web Highlights, a popular Chrome extension designed to make saving and highlighting important content on the web easier. Learn about the front-end architecture built with Web Components and the use of Vue.js for the progressive web app.

Tech Stack Behind Web Highlights - PDF & Web Highlighter
Tech Stack Behind Web Highlights — PDF & Web Highlighter

Web Highlights is a Chrome extension designed to make highlighting and saving important content on the web easier. With over 10,000 weekly users, the extension became a valuable tool for many people who need to keep track of important information online.

In this article, I’m excited to share with you the technology stack that powers the extension and brought this project to life.

Introduction

When I first began developing Web Highlights 4 years ago, I wasn’t overly concerned with the technology stack. At the time, it was simply a fun side project — an opportunity to try my hand at building a Chrome extension for the first time.

Like many developers, I turned to my toolbox of technologies and got started on building Web Highlights.

Even though the tech stack has changed a bit in the last few years, I’m still very happy with my initial choice. Without changing anything fundamental, my extension is capable of synchronizing all highlights with the cloud and web app. Up until now, it can handle the requests of 10,000 users.

Frontend

At the core of the Web Highlights Chrome extension are two primary front-end applications:

  • the extension itself, which is loaded into the user’s browser,
  • and the associated Web App that can be accessed at web-highlights.com.

Browser Extension

At the heart of Web Highlights is obviously the browser extension itself. This application part is loaded in the user’s browser, enabling text highlighting on any web page and PDF.

It also displays a collapsible and expandable sidebar that shows all the user’s text highlights, notes, and tags.

Web Highlights Chrome Extension — Sidebar & Highlighter
Web Highlights Chrome Extension — Sidebar & Highlighter

Those who follow my articles will probably already guess that a large part of my front-end architecture is built using Web Components.

Web Components are reusable client-side components based on official web standards. They are an excellent way of encapsulating functionality from the rest of our code. Not only that, but you can reuse them in every web application and web page.

Web Components offer numerous advantages, so I used them from the beginning of developing the browser extension. To streamline the process of creating Web Components, I opted to utilize the Lit library. This lightweight library, maintained by Google, is specifically designed for building web components and makes the development process significantly easier.

I have discussed the benefits of Web Components in various articles previously. However, the most significant advantage that saves me a lot of work is the reusability of components.

Will Web Components Replace Frontend Frameworks?
They are built to solve different problems.

Because of the easy reusability, I can easily include some components from the extension in the associated web app, which I’ll get to in more detail in the next section.

I also use Typescript like in all of my other applications as well. Furthermore, I included Redux to manage and synchronize states within the application.

Web App

In addition to the Chrome extension, Web Highlights also includes a progressive web app (PWA) that allows users to access their saved highlights from any device.

Here is what the dashboard looks like:

Web Highlights dashboard
Web Highlights dashboard

I chose to use Vue.js for the PWA somewhat impulsively. This was during the early days of Vue.js, and there was a lot of buzz surrounding it. I was enthusiastic about learning it, which prompted me to initiate building the WebApp’s frontend with it.

Nevertheless, as already mentioned, I reuse many Web Components from the extension in Vue.js. This saves me a lot of duplicated code and work. When looking at Web Highlights’ dashboard, you might have noticed that some components look very similar to the ones in the extension.

The reason for this is that they are essentially identical, except for the fact that they are loaded within my Vue.js app. To illustrate this, let’s compare the screenshot from my extension with the Vue.js PWA and note their similarities:

Web Components in Web App and Chrome Extension
Web Components in Web App and Chrome Extension

You can see that the rich editor, the share button, and the toolbar are used in the web app and the Chrome extension. Many more components are used in both applications. However, I hope this comparison does a good job of showing the benefits of reusing web components.

Blog

Besides the frontend, I also run a blog under the subdomain web-highlights.com/blog. The main motive for setting up the blog was to rank higher on Google.

In the last few weeks, I have dealt extensively with the topic of SEO and understood that a blog on one’s domain could significantly improve the Google ranking. When it comes to SEO, then there is no way around it.

Hosting a blog and creating content on my website was a game-changer. If you want to learn more about it, read this article:

3 Instant Ways to Increase Your Google Ranking
Anyone can implement these three essential points to make their product visible on Google, Bing, and Co.

When it comes to hosting a blog, there are several choices available. However, I opted for a self-hosted Ghost instance.

Ghost It comes with modern tools to build a website, publish content, send newsletters & offer paid subscriptions to members. —  https://ghost.org/

I created a digital ocean droplet and set up Ghost on it. This is easy, as Ghost and Digital Ocean provide excellent getting-started articles and documentation.


Backend

When choosing a server, it was essential to me that I could also use JavaScript/Typescript. For two main reasons:

  • I simply know JavaScript best
  • I can share code between the server and frontend

The second point is particularly important to me. The fact that I can reuse code in both the frontend and the backend makes my code so much cleaner. In my article “Share Code between React Client and Express Server,” you can learn how to implement this using a mono repository.

Share Code between React Client and Express Server
Set up a mono repository with yarn workspaces

Main Server

A huge part of my application forms one server, which relies on Nest.js. Nest.js is a powerful Node.js framework that provides a robust set of tools for building scalable and efficient server-side applications.

The server synchronizes users’ highlights, bookmarks, tags, and notes with the cloud. This functionality allows users to access their highlights not only within the extension but also from anywhere there is an internet connection. Users can log in to the web app, which downloads all their highlights from the server. It is also possible to share your research with friends who do not have the extension.

To ensure secure authentication, the server implements JSON Web Tokens (JWT) technology. Furthermore, I integrated Google Sign-In with Firebase.

Furthermore, my server handles a few asynchronous processes I implemented with CRON jobs. For example, users can set email reminders that are then executed every hour in a CRON job.

To make some recurring queries faster and more efficient, I also introduced a caching system that simply uses the NodeCache to cache time-consuming database queries and return them faster.

Micro Server

In addition to the main server, I implemented a small microservice using Express.js. This microservice is responsible for exporting HTML to PDF files using the Puppeteer library.

I had initially considered implementing this functionality in the main Nest.js server, but given the large size of the Puppeteer library and the resource-intensive nature of its operations, I decided to offload this functionality to a separate microservice. This way, I can keep the central server lean and fast while still providing the necessary PDF export functionality via the microservice.

Database

The Web Highlights Chrome extension relies on a MongoDB database to store user data. MongoDB is a popular NoSQL database with high scalability, availability, and performance.

To model the data in the database, I am using a popular object data modeling (ODM) library for MongoDB. Mongoose provides a simple and intuitive API for defining schemas, creating queries, and validating data.

The database is hosted on MongoDB Atlas Cloud Database, which handles all the complexity of deploying and managing my database. Additionally, it offers the security of automatic backups.

Hosting

Server

At present, my central server and microservice are being hosted on Heroku Dynos, which offers flexible hosting options for my applications. Using Heroku has been very convenient for me as it allows for effortless deployment from GitHub and enables me to set up a testing server for pre-production tests by deploying from my development branch.

Frontend

I have set up a Digital Ocean droplet to host my Vue.js web app’s frontend. A configured A-record in my domain provider, Strato, directs the domain web-highlights.com to the IP address of my Digital Ocean droplet.

The droplet is configured to serve the app statically. Additionally, I set up an NGINX server to serve my Ghost CMS blog instance from the subfolder /blog of the domain. With this configuration, visitors can easily access the web app and the blog from the same domain.

Testing: Jest + Cypress

Initially, like many others, I developed my application without any unit tests or integration tests. However, over time, I added a significant number of unit tests and integration tests, which have helped me avoid many issues.

Although it was challenging to test the Chrome extension fully integrated, I established a test environment where I could launch and test my application locally. Using Cypress, I have tested almost every feature of my application. Additionally, I have implemented many unit tests for complex logic, for which I utilize Jest.

Final Thoughts

That’s it. Of course, I did not mention every single piece of technology or library I am using but I hope this gives you some valuable insights. Maybe you can even adopt some things to develop your own Chrome extension.

Here’s a quick summary of all technologies:

  • Frontend: Web Components + Lit, Vue.js, Typescript, Redux, Ghost CMS
  • Backend: Nest.js, Express.js, JWT, Firebase Auth
  • Database: MongoDB, Mongoose, MongoDB Atlas Cloud
  • Hosting: Heroku, Digital Ocean, Strato
  • Testing: Jest, Cypress

I hope you enjoyed reading this article. I am always happy to answer questions and am open to criticism. Feel free to contact me at any time 😊

Get in touch with me via LinkedIn or follow me on Twitter. Also, check out my PDF & Web Highlighter Chrome extension if you haven’t. Follow me on Medium for more articles like this.