Connect your Hashnode blog to a Remix app with the Hashnode API.

Connect your Hashnode blog to a Remix app with the Hashnode API.

Frameworks, frameworks everywhere!

If you are a JavaScript developer, you know that frameworks are in no short supply, and one of the new kids on the block is Remix. Remix touts itself as "a full stack web framework that lets you focus on the user interface and work back through web standards to deliver a fast, slick, and resilient user experience.", and I had my doubts about it at first, simply because initially it wasn't open source, and I was having a hard time understanding this as a devoted fan of NextJS, the React framework from Vercel. How could a JavaScript framework warrant a hefty price tag for licensing and use, all while still in beta at that? All that uncertainty quickly changed once the creators decided to go open source and let the public in on what they had been working on.

I digress a little bit, but a bit of backstory helps paint an important scene. Remix, to put it simply, was more than a breath of fresh air. Sure, it was a React framework, but at its core was using web fundamentals that had been left behind in the aftermath of the SPA days. It made everything that a web app needs to function feel so easy to achieve. It made me enjoy building project apps for fun again. And their community has been quite welcoming and forthcoming with knowledge, and I am here today to share a little bit of that knowledge myself.

I recently rebuilt and redesigned my personal website, and wanted to use it as a sandbox to gradually build upon my understanding of Remix, and one of the tasks I found myself facing was starting this blog. Sure, there are LOTS of ways to implement a blog in your React app, but I am a huge fan of what the people at Hashnode have built for developers, it's truly a first-class blogging experience with basically zero friction, and so I opted to use their platform instead.

What is the Hashnode API?

Hashnode uses a GraphQL API for interacting with their platform programmatically and can be found at https://api.hashnode.com/. All it takes is a simple query and you have their whole platform at your disposal. For instance, you can:

  • Fetch posts and publications from a user

  • Follow a user

  • Create or Delete a post

  • and so much more.

We are just going to cover fetching our own articles today, but feel free to play around with their API endpoint and see all the ways you can use it!

Fetching our articles

Remix makes queries especially easy, and is typically done at the route level. It is built on top of React Router, so if you have been using their latest versions, this should seem familiar. Remix lets us export a simple helper function for each route called a "loader", which simply loads your data from whatever source you want, and runs on the server before passing that data to your route component.

To fetch our posts, we are going to use the Fetch API to make a POST request to the hashnode API endpoint, and provide it with:

  1. A GraphQL query, which we are going to call myArticlesQuery

  2. a variables property, which is an object containing our username, and the first page of articles we want to request, which is 0 so we get the newest articles.

~app/routes/index.tsx

export const loader: LoaderFunction = async ({request}) => {
  const data = await fetch("https://api.hashnode.com/", {
     method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        query: myArticlesQuery,
        variables: { page: 0, username: "YOUR_USER_NAME" },
      }),
  });
};

We are using async/await here and your loader function should always be an async function as it usually runs some server logic.

Now that we have our request ready, let's define our query so that we can get our data. GraphQL queries are handled with template literal strings in JavaScript and ours will look something like this:

~app/lib/queries.tsx

export const myArticlesQuery = `
  query GetMyArticles($page: Int, $username: String) {
    user(username: $username) {
      publication {
        posts(page: $page) {
          slug
          title
          dateAdded
          brief
        }
      }
    }
  }
`;

As you can see, our query takes two arguments: our page, and our username, as well as the types for each.

Now that we have our query ready, let's go back to our loader function, as we still need to access our posts and return them so our route component can use them. We have provided the query with some property names such as slug, title, dateAdded, and brief, which we can use in our component later.

~app/routes/index.tsx

export const loader: LoaderFunction = async ({request}) => {
    const data = await fetch("https://api.hashnode.com/", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        query: myArticlesQuery,
        variables: { page: 0, username: "YOUR_USER_NAME" },
      }),
    });

  const result = await data.json();
  const articles = result.data.user.publication.posts;

  return { articles };
};

Our posts are in an array that is nested within a few properties inside the promise returned from our await data.json() statement, and we can return a new object containing our articles.

Consuming our articles

Now that we have some data returned from our loader function, we can consume it in our route component and render our articles however we would like. To use data from a loader, Remix provides us with a handy, aptly named hook called useLoaderData.

~app/routes/index.tsx

export default function HomePage() {
  const { articles } = useLoaderData();

  return (
    {articles.map(article: Article) => {
        return (
          <BlogArticlePreview article={article}/>
        )
    }}
  )
};

Of course, your components may look a bit different, but basically, the articles data that our loader function returns is an array of our most recent articles, and we can choose to render them how we want, and just link to our articles on Hashnode as needed, or you can also add more properties to your query for more data and simply render your whole article on your own site if you prefer.

To link to your articles on Hashnode directly, you will need your hashnode blog's URL, and the slug from your article object, like so: https://<your hashnode blog URL/${article.slug}>

Take Away

In this article, we talked a bit about Remix as a framework and how they make their developer experience seamless for us, as well as how to query Hashnode's GraphQL API for our personal blog posts. This API is pretty useful to know as a developer who writes, and there's a lot you can do with it.

✌️ Thank you for taking the time to read this blog post!

If you enjoyed this content, be sure to subscribe to my newsletter for updates when I publish new content, and follow me on Twitter @scott_prins, where I share more of my thoughts on JavaScript development, startups, and more.

Until next time!