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.
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:
- Upwork
- Food apps
- Project management tools
- Customer feedback tools
- Roadmap tools
And the list continues.
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:
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
And in one minute change it to something like this:
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)
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.
Add new types of votes you want to monitor.
Watch analytics of who clicked / how many / which days / what's the best area etc.
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.
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)
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
andMULTI
to add transactions and prevent race conditions where the counter will have a different number than what you expect.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.
NestJS MicroService Group Consumers will listen to the Kafka topics, pull in information, and add it to the database.
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)
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 🤞
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
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)
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
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:
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!
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?
:)
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.
Ok!
If I have time this week I might start just creating the markup and styling the component.
I'll stay in touch.
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
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!
Thank you so much Lionel! ❤️
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?
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?
Yes of course. Thank you!
❤️
Just wow 🤩 you outdid yourself this week. Such a wide spectrum of technologies - in the end simplicity 👏
Thank youn so much Marc!
According to Hackernews, I did an overkill infra haha
Hahahaha love it 😍
You're a freaking guru. Great Job!
Haha, thank you so much ❤️🚀
Congrats, awesome stuff David!
Thank you sooo much!
Nice idea!
Thank you so much!
This is really great 👌👌
Thank you! ❤️
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?
Yes! for the simple option of having an upvote that can def work.
But my questions was:
I might be wrong about them all.
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!
Great article @nevodavid
Thank you so much ❤️