Building my personal website - Part 2: Displaying my blog on my site with Hashnode API

ยท

3 min read

So far we've created the MVP of my website and deployed and hosted it on Vercel which I have a walkthrough on here. It is a simple website, and only displays the necessary information, but we want to implement some dynamic features and showing my posts on my site is the perfect way to start.

One thing I need to have in mind when it comes to my website is to reduce the manual work done and lower the maintenance. I want the site to show the info dynamically on my site and update automatically meaning I need one single data source. I'm writing my articles on Hashnode API and can query the data for display so that i don't need to export the markdown to my site and deploy it.

The Hashnode API is built with GraphQL and has a UI to test and build your query and mutations.

Querying the Hashnode API from Next.js with Fetch API

Now we have the simple GraphQL query to query our posts. We want the leverage the SEO benefit of the content from my posts, and therefore we will fetch all the posts serverside and ship it to the client. The code snippet below also shows the implementation of passing the page argument to the query so we can keep loading the next chunk of articles.

const fetchPosts = async (page: number) => {
  const headers = {
    "content-type": "application/json",
  };
  const requestBody = {
    query: `query  fetchPosts($page: Int) {
      user(username:"kasp9023") {
         publication {
          posts(page: $page) {
            title
            slug
            dateAdded
            brief
          }
        } 
      }
    }`,
    variables: {
      page,
    },
  };
  const options = {
    method: "POST",
    headers,
    body: JSON.stringify(requestBody),
  };

  const response = await fetch("https://api.hashnode.com", options);
  const data = await response.json();

  const {
    data: {
      user: {
        publication: { posts },
      },
    },
  } = data;

  return posts;
};

This is just a really simple way to fetch the posts without any premature optimization or grabbing some third-party libraries to enhance the functionality. I could have gone with Apollo or React Query, but this does the job and at the same time, no third-party libraries are needed!

Then we are fetching the posts in the GetServerSideProps function provided by Next.js and send the posts as props to the client before interacting over each post and rendering the following component the show the post summary

function Post({ post }: { post: Post }) {
  return (
    <a
      href={`https://blog.kasperdue.com/${post.slug}`}
      rel="noref noreferrer"
      target="_blank"
    >
      <div className="d-flex mb-16">
        <h3 className="mb-4 text-4xl font-extrabold text-slate-800">
          {post.title}
        </h3>
        <p className="font-light text-slate-700">{post.brief}</p>
      </div>
    </a>
  );
}

Now every post from page 0 will be displayed as the initial post that is loaded. At the bottom "Load More" button is implemented which has a click event attached that calls the following function to load more posts and append them to the existing posts.

  const loadMorePosts = async () => {
    setIsLoading(true);
    const newPage = page + 1;
    const newPosts = await fetchPosts(newPage);
    setAllPosts([...allPosts, ...newPosts]);
    setPage(newPage);
    setIsLoading(false);
  };

The final result is the following and we still haven't compromised with any of the Lighthouse metrics at all! ๐ŸŽ‰

Thanks for reading along! Let's see what the next feature we will implement.

Check out my website at kasperdue.com or i you have any question, reach out to me on LinkedIn

ย