DEV Community

Cover image for 🫰Clickvote: Open-source upvotes, likes, and reviews to any context 🔥
Nevo David for Gitroom

Posted on

🫰Clickvote: Open-source upvotes, likes, and reviews to any context 🔥

TL;DR

I built an open-source app to add upvote, like, and reviews anywhere.
And while it sounds easy, I kind of broke my head on the architecture.
Let's talk about it.

Image description


What the hell are you building? 🤯

In the last decade, I had the chance to develop "reviews", "upvotes", and "likes" in multiple places, and I have also seen them in numerous areas like:

  • Reddit
  • Facebook
  • Instagram
  • Upwork
  • Food apps
  • Project management tools
  • Customer feedback tools
  • Roadmap tools

And the list continues.

Ranking:
Type1

Likes:
Type2

Upvotes:
Type3

And so far, I have realized it's pretty simple to build it in-house - until it's not.

You need to take care of the following:

  • Showing real-time updates of likes, upvotes, and reviews between clients
  • Learn about your members through deep analytics
  • Deal with an unlimited amount of clicks per second (depends on your scale)
  • Actually manage this

The dream 😴

Well, it's not far-fetched...
What if you could put a super simple component that will add this functionality instantly to you (like literally) in 5 minutes?

Here is the code snippet:

Snip

You can wrap your application with ClickVoteProvider, providing the current user's id.

And then, distribute different ClickVoteComponent around your app with a dynamic id of the thing you want to vote to.

Once you interact with the voting (LikeStyle), it will update all the other users watching the same component with the new value.

So we can take the simple dashboard in Novu

Novu

And in one minute change it to something like this:

Novu Upvote

Ok, now that we all understand what we are trying to build.
Let's see what it actually looks like.


The Graph! (I added colors)

Graph

It looks a bit complicated for a simple like 🤔
But let me try and explain.

The Analytics Board:

Like in every other system, you have the dashboard.
It's made out of NextJS(for the front end) and NestJS (for the backend), and includes MongoDB.

  1. Add new types of votes you want to monitor.

  2. Watch analytics of who clicked / how many / which days / what's the best area etc.

  3. Provide a way for the customer to attach the data source they want to be informed of once there is an interaction (they might want to change their system).

The User Application:

Here is where it becomes tricky.

  1. We create a WebSocket server that all the clients can connect to receive instant updates about new likes and upvotes. (I have checked Server Sent Events - SSE but there is a hard limit for 6 on the browser, so decided not to)

  2. The WebSocket server needs to question and updates the number of votes while handling a heavy load of click; for that, we use Redis, which gives us options like WATCH and MULTI to add transactions and prevent race conditions where the counter will have a different number than what you expect.

  3. Next is Apache Kafka - If you plan to have thousands of likes every second, you can't just insert it into your database (it will crash). Also, you want something to ensure the information gets into the database and does not fail. I have chosen Kafka because it's popular, but you can easily select another service like Apache Pulsar. So we send everything to Kafka.

  4. NestJS MicroService Group Consumers will listen to the Kafka topics, pull in information, and add it to the database.

  5. I have chosen to use Timescale as a time-series database. I could use something like Clickhouse or Redshift. I like Timescale because it's Postgres with some "plugins" It means that the open-source community can just choose to use Postgres instead of a time-series database. (for a lower scale)

  6. Another NestJS MicroService Group Consumer that will send the information to the User application according to their preferences (API, direct DB insert, another Kafka), anything they choose.


How much will it cost me to host this stack? 🤣

If being cheap:

  • Vercel Frontend (NextJS) $20
  • Timescale $31
  • Upstash for serverless Kafka / Redis ~$70
  • Digital Ocean Websockets server $25
  • Digital Ocean Backend $25
  • Digital Ocean 1 Worker (Consumer) $25
  • MongoDB Atlas $20

I believe not less than $216.

It can obviosly sit in one server with a docker-compose, but it will not last long.

At a later point I believe that the backend / workers / websockets should be Dockerized, Kuberneterized and sit somewhere on AWS.

Will get there 🤞

Making Money


Things that are definitely missing

  • Option for non authenticated users to see the results.
  • Anonymous voting with a fingerprint.
  • More varinats of the style button (that I haven't thought about)
  • Sync votes from different applications (Bi-Directional)
  • Motivation - help me? 😅

What's the adoption aspect of it

So far, it looks like it will mostly fit B2B2C companies like:

  • Social Media
  • Job websites
  • Documentations? (if there's an anonymous feature, most likely work with something like Fingerprint.com)
  • Reviews websites (Glassdoors?)
  • Maps websites

Having B2B businesses adopting this requires some education in the market. (some do it already)


Show me the code 👀

Well, there is no documentation yet.
It's still a work in progress.
You can find there:

  • Nx Monorepo architecture.
  • NestJS Backend.
  • NestJS Kafka Microservice.
  • NestJS Websockets.
  • NextJS - looks bad, I know 🤣

But please show your support with a star ⭐️
It will help me know if there is a need for that.

https://github.com/clickvote/clickvote

Shoot Stars

Sorry for the ugly design 😛
(Logo made with MidJourney)

Follow me on Twitter! Let's talk 🙇🏻‍♂️

Do you think there is room for a product like that?

Top comments (29)

Collapse
 
ismaestro profile image
Ismael Ramos 🚀

Hi Nevo!

First of all, congratulations on this project! It looks simply amazing!

As a front-end developer, I would like to know a little bit more about that aspect. If I understood correctly, in the end, if I want to use your service, do I need to add your component to my website? Is it designed as a web component? If not, would I be able to use it in an Angular app, for example?

I love the project, and once again, congratulations!

Isma

Collapse
 
nevodavid profile image
Nevo David

Hi Isma,
At the moment the project is self-hosted and you would need to host the entire project in order to use the component!

Yes, you need to add the component to your website, as this is the first version there is only a React Component. I hope the in the coming months I would have:

  • a web component
  • an angular component
  • a vue component
  • a svelte component

This is the NX library of the React component
github.com/clickvote/clickvote/tre...

In the future I would also host the entire service, so you can only use the component without hosting it yourself :)

I hope it helps!

Collapse
 
ismaestro profile image
Ismael Ramos 🚀

Nicee!

I was thinking about helping in that part, maybe I can create a PR to add a web component or an angular component. Are you open to that?

:)

Thread Thread
 
nevodavid profile image
Nevo David

Of course!
But I am going to change the architecture a bit.
I got a bit of backlash on building something too complicated.
I might start by removing timescale and kafka.

Thread Thread
 
ismaestro profile image
Ismael Ramos 🚀

Ok!
If I have time this week I might start just creating the markup and styling the component.
I'll stay in touch.

Thread Thread
 
nevodavid profile image
Nevo David

Great!
I added some setup instructions to make it a lot easier.

I have already created the angular directory over
/libs/angular-component

And it's already published to npmjs on
npmjs.com/package/@clickvote/angular

Collapse
 
softwaresennin profile image
Mel♾️☁️

great great great stuff...

The issue that I have and I guess some others have is taking all what we know in this and that and piece it all up together and create solutions like this you just did.

I really really really want to say KUDOS to you for stepping out and sharing this. Many others have ideas but the implementation ... like what you just did here is where they get stuck and drop the idea.

Again Kudos!

Collapse
 
nevodavid profile image
Nevo David

Thank you so much Lionel! ❤️

Collapse
 
gyurmatag profile image
Varga György Márk

Awesome. I will look into the project a little bit deeper later.
Haven't you considered using Supabase for most of the backend / real-time features of you application?

Collapse
 
nevodavid profile image
Nevo David

Superbase are really amazing for that, and I am using them with projects like
libraries.github20k.com

For the public upvotes.
I feel that as a closed sourced product that will probably be my go to.
But as an open-source product it must be flexible to any need.

If I put Supabase, I would force open-source users to use Supabase (they are great, but limiting)

Does it make sense?

Collapse
 
gyurmatag profile image
Varga György Márk

Yes of course. Thank you!

Thread Thread
 
nevodavid profile image
Nevo David

❤️

Collapse
 
mfts profile image
Marc Seitz

Just wow 🤩 you outdid yourself this week. Such a wide spectrum of technologies - in the end simplicity 👏

Collapse
 
nevodavid profile image
Nevo David

Thank youn so much Marc!
According to Hackernews, I did an overkill infra haha

Collapse
 
mfts profile image
Marc Seitz

Hahahaha love it 😍

Collapse
 
suede profile image
Yuval

Great article @nevodavid

Collapse
 
nevodavid profile image
Nevo David

Thank you so much ❤️

Collapse
 
arndom profile image
Nabil Alamin

This is really great 👌👌

Collapse
 
nevodavid profile image
Nevo David

Thank you! ❤️

Collapse
 
zevireinitz profile image
Zevi Reinitz

You're a freaking guru. Great Job!

Collapse
 
nevodavid profile image
Nevo David

Haha, thank you so much ❤️🚀

Collapse
 
matijasos profile image
Matija Sosic

Congrats, awesome stuff David!

Collapse
 
nevodavid profile image
Nevo David

Thank you sooo much!

Collapse
 
oba2311 profile image
Omer Ben Ami

Nice idea!

Collapse
 
nevodavid profile image
Nevo David

Thank you so much!

Collapse
 
schemetastic profile image
Schemetastic (Rodrigo)

Wow! Really cool project! I already gave you a star on GitHub.

As a front-end developer, it's a little hard for me to understand why would you need such a huge architecture for a component like this... don't you think something like Pocketbase or Supabase would get the job done for both, the component and the admin?

Collapse
 
nevodavid profile image
Nevo David

Yes! for the simple option of having an upvote that can def work.
But my questions was:

  • What if you need daily analytics around your likes in the app?
  • What if you are at scale? (Instagram)
  • What if you don't want to waste time in building it at all? even we Supabase you will need to have the logic of getting the likes, counting, preveting race condition and so on :)

I might be wrong about them all.

Collapse
 
schemetastic profile image
Schemetastic (Rodrigo) • Edited

I think that PocketBase is good for small to medium-large (many thousands of requests per day), and the PocketBase SDK could be used for both, handle the votes and also get and post data to be used with the admin and analytics.

But as you say, if you want to create a huge app, maybe like Instagram, PocketBase or Supabase may not be the best fit for those kind of projects.

Pretty cool project by the way!

Collapse
 
lewiscowles1986 profile image
Lewis Cowles

What about w3c recommended webmention which enables likes and comments on any URL?

webmention.io