🎤 Building the biggest list of useful open-source libraries 🎉🥳😎
Tags: webdev, programming, javascript, tutorial
Published: 2023-05-25 11:59:40

# TL;DR
Every day we see "awesome" GitHub lists. They are great.
The main problem is that it sometimes needs to be updated.
Maintainers need more time, or they leave the company.
It also needs to reflect usefulness.

I have decided to build a list that will do two things
- Help new libraries get some traction.
- Let people vote for their favorite library.

![Gotlist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fizwpnag0ak0m2gutorv.gif)

<hr />

## Before we start
I am super happy to tell you how I build it.
But first, if you have a GitHub repository, [please add it](https://libraries.github20k.com) to our website here.
You can later be able to find it here:
https://github.com/github-20k/awesome-opensource
![add library](https://user-images.githubusercontent.com/100117126/239861952-340f5ca4-b13f-450f-b750-8d5c028d809d.gif)

<hr />

## I wanted to save money 🤑 💰
I have the technicality level of building my own CMS and hosting it on AWS - taking care of the scaling and CI / CD. But it would take me a ton of time and also money.

So I bought a $2 monthly WordPress host from [DreamHost](https://www.dreamhost.com/).

Don't fall off your chair - yes, it's slow, and yes, it won't be able to survive significant traffic. So I used it + cached almost every possible result on the website (including the search).

The good thing about WordPress is that you can use their API out of the box with GET - `/wp-json/wp/v2/posts`; also, adding an advanced custom field plugin reflects automatically on the results.

![GetResults](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnobwyrpyc2rcg06wgbw.png)

## Limitation 🙅🏻‍♂️
- Slow; everything must be cached.
- Impossible to perform "search."
- Long build times (everything is cached).
- No real-time updates.
- Almost impossible to implement infinite scroll (must be pagination based)

<hr />

## NextJS to the rescue
I picked [NextJS](https://nextjs.org/). They have a great SSG mechanism for caching all the pages. I didn't use the new app router approach, I don't find it playing nicely, but I did do [a tutorial about](https://www.youtube.com/watch?v=RXhC67ypom0).

I have cached everything 🤣
We have seven routes
- Trending list (/page/1)
- New List (/new/1)
- Categories list (/productivity/1)
- Languages list (/language/javascript/1)
- Categories + Languages list (/language/javascript/category/productivity/1)
- Site information
- General search (I will explain how I implemented it)
- And generate tweets (we will talk about it later)

You can probably imagine that the "Categories + Languages" list is the biggest, and it's true; if I added one more filter like that, I would have thousands of pages.

![Router](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hur1j1c4j0q7rv3x1ihc.png)

[Vercel](https://vercel.com) free plan, play nice when you don't do background processing.

But if you do need background processes, you will experience a problem with the API.

Serverless Function - Free version 10 seconds limit, Pro version 60 seconds.

<hr />

## Why do I need an API if everything is cached

Thank you, Nevo, for asking.

I wanted to let people add their own libraries.

For that, I need to do multiple things:

- Use GitHub GraphQL to fetch the repository information - avatar, owner, and home page URL.
- Use ChatGPT 😉 on the README.md file to summarize it.
- Insert everything into WordPress.

You can probably guess that it takes time to use ChatGPT for long texts.

**So I decided to do two things:**
- Do the first job (GitHub GraphQL) sync with one of the /API paths. (around 10 seconds)
- Use [Serverlessq](https://www.serverlessq.com) to push all the information into a queue running another API route. It will retry it three times in case it fails (around 40 seconds)

<hr />

## The upvote mechanism 👆🏻 ⬆️
I save the number of upvotes over WordPress; it's a simple API request that does +1 on the record.
I know - it's an atomic action, there is no queue, and it can cause a deadlock. When I get to the time, there is massive traffic to the website. I will move it to a queue.
For now, I have a more significant concern.

How do I show the new amount of upvotes without re-rendering the page?

I started to try complicated caching stuff and API. But then it hit me - [Supabase](https://supabase.com).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/48rb6z63j57066tfupo1.png)

### Supabase
I did genius stuff - still proud of myself.
I created a new table on Supabase called "votes" and added the date the vote was counted.
I also added an additional props in NextJS getStaticProps called date - and set there the current date.

So every time I have a new cache build, the page gets the new date. But I just use the old date if there is no new build.

All that was left to do was to ask Supabase - to give me all votes after this date.

![Cache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lh9r3lvb5o48iziy0tvo.png)

Then I just show Cached votes + Supabase votes.

And when there is a new build, I would probably get from Supabase that there are 0 recent votes.

## Get tweeted!
I have lately seen many tech influencers making lists of the ten best libraries; I thought that I could help influencers and library owners by letting influencers build lists on the website and tweet them.

![Tweet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0pdeuy92f6ue9bz6opr.png)

![tweeted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ei8b46ih202mkxssd9vj.gif)

Building the HTML on the right side was easy; the problem I faced was how to make a picture in the end.

I was looking into [Remotion](https://www.remotion.dev/), but the problem is that it's [not playing well](https://www.remotion.dev/docs/miscellaneous/vercel-functions) with Vercel.

I decided to save some computing power by using [html2canvas](https://html2canvas.hertzen.com/) and letting the user render the images.

The thing is that if you render images and it's on a different domain, you'll get a CORS problem, so I have made a slight rewrite for all the photos:

![Rewrite](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nurzflqgmvz0cy5wupgb.png)

That's it! I hope it was helpful to you!

<hr />

## Can you help me out?

Star the GitHub repository so more people can get visibility into excellent new tools 😎

https://github.com/github-20k/awesome-opensource

Check also [How to get GitHub stars](https://howtogetgithubstars.com)