lazyd3v blog

šŸ· Vivino + Systembolaget = new chrome extension

Posted at ā€” Apr 10, 2020

I like to drink good wine, itā€™s one of my favorite drinks. Also, Iā€™m a huge fan of Vivino app. If you donā€™t know it is an awesome app with a big collection of wine reviews. This collection is that big, so I couldnā€™t find a wine that wasnā€™t registered in Vivino.

Also, I live in Sweden. Thereā€™s only one retail store allowed to sell alcoholic beverages, itā€™s called ā€œSystembolagetā€. Usually, I go there, start taking a photo of every available wine and after ~20 minutes I choose some. Yeah, I look like an idiot, but always choose a good wine. Recently I thought maybe thereā€™s a way to optimize the process of choosing the right wine?

Systembolaget has a very nice website and webshop. You can look what is available to deliver or can be picked up in the nearest store. But thereā€™s no Vivino score or at least reviews from other buyers.

Vivino has a web version of app as well. Thereā€™s no possibility to scan labels via photo, but itā€™s not needed actually. You can just search for wine by name and find more details. Unfortunately, you canā€™t filter wines that available in the nearest Systembolaget. Of course, you can copy-paste the name, but itā€™s even more annoying than taking a photo of every wine in the store.

ā€œChallenge acceptedā€ - I said and started to think about how to integrate Vivino score into Systembolaget website.

It was obvious that I needed to create some chrome extension to achieve that. After some research, I concluded that Vivino doesnā€™t have any public API and has no alternatives. So I started to think about how can I use their website for my needs.

The answer was simple - just use the search functionality. Make a request, parse HTML using cheerio and extract the info. Quite simple!

But as always - everything is not as simple as it seems. CORS šŸ˜”. Due to security reasons, you canā€™t make cross-origin requests from content scripts. But thereā€™s another way to do it - fetch URLs via background script as advised here

Ok. I can extract information from Vivino by name, how to add this info to Systembolaget website. I looked to the markup, found some places where I can attach Vivino score ā€¦ and itā€™s working! wow!

Then I scrolled down and realized they have a lazy-loading mechanism on a wine list. Ok - just add MutationObserver and append Vivino score after the list item is loaded. Unfortunately, it didnā€™t work. Maybe Iā€™m stupid and missed something or thereā€™s some magic in their app - but MutationObserverā€™s callback didnā€™t want to be executed. My theory is because of using React, it recreates DOM nodes and doesnā€™t attach MutationObservers to a new one. But Iā€™m not sure, Iā€™m not an expert at such low-level things, itā€™s just my theory.

I came up with a simpler solution - just attaching scores on list items on a scroll. I also applied debounce to achieve better performance.

Another thing for better perfomace is cache. I used axios-cache-adapter for cache mechanizm itself, and localForage with localforage-webExtensionStorage-driver to store this cache in extensionā€™s local storage.

Hereā€™s the screenshot how it looks like: Screenshot

Source code is available here

comments powered by Disqus