Hashnode Deck - discover new and trending content on Hashnode with ease!
When I only started using Hashnode, I noticed different tabs: Best, Featured, and Recent. To check all the content, I needed to switch between them. And to do that, after the long scroll, I needed to scroll back to the top. Quite a tedious task, isn't it?
So what if I tell you that you can save some time and discover content on Hashnode easier by minimizing these micro-interactions and then spending this time reading interesting articles?
Meet Hashnode Deck - a live feed that enables you to discover new and trending content on Hashnode with ease!
You can start using it right away on hashnodedeck.com or keep reading this article to learn more about the technology stack and the challenges I had when building it.
Setup
The project setup was relatively straightforward. I did everything based on the documented process that I published earlier: How to wire up Next.js with Tailwind CSS and Typescript quickly.
Design
The design wasn't a problem either. I'm a big fan of Tweet Deck, so I decided to implement the same pattern here using a standard color palette Tailwind provides.
Challenge
The biggest challenge was data fetching with pagination. I had to decide what tool to use to connect the app to the Hashnode API. I was choosing between Apollo Client and React Query.
I read many great reviews about React Query. So after some evaluation, I decided to give it a shot.
What can I say? I make many mistakes when making guesses, but this time I was entirely right because React Query exposes the useInfiniteQuery hook. It helped me to implement a pagination query functionality in no time.
This is a simplified example from the official documentation:
import { useInfiniteQuery } from 'react-query';
function Projects() {
const fetchProjects = ({ pageParam = 0 }) =>
fetch('/api/projects?cursor=' + pageParam);
const {
data,
isError,
isLoading,
fetchNextPage,
} = useInfiniteQuery('projects', fetchProjects, {
getNextPageParam: (lastPage) => lastPage.nextCursor,
});
if (isLoading) {
return <p>Loading...</p>;
}
if (isError) {
return <p>Error: {error.message}</p>;
}
return (
<>
{data.pages.map((group, i) => (
<React.Fragment key={i}>
{group.projects.map((project) => (
<p key={project.id}>{project.name}</p>
))}
</React.Fragment>
))}
<div>
<button onClick={() => fetchNextPage()}>Load More</button>
</div>
<div>{isLoading}</div>
</>
);
}
As you can see, it is pretty straightforward.
Summing up
It's been a lot of fun building Hashnode Deck. It is a great example of how new technologies and established practices help us quickly provide interesting solutions for problems and improve user experience.
I believe that Hashnode Deck's development is just started, and I will try to implement new features by following Hashnode API enhancements.
Cheers! ❤️