If you have a portfolio website and you also do blogging then it is only just fair to have representation of your blogs on your website. Same reason for me to integrate Hasnode blogs on my portfolio website. I am currently building my portfolio website and I have a blog section in it. I was looking for a way I could easily set up my blogs on my portfolio.
The problem that I had was I didn't know how I should approach it. Initially, I was thinking of building my own layout for the blog section and placing all the blogs in my source code. But then after spending some time on the internet and looking for the easy way. I finally found a way that let me integrate my Hashnode blog into my portfolio.
Hashnode API
Hashnode has a GraphQL api that exposes Hashnode blogs to the user. In the below attachment, you can see that I have fetched data for the user name hat52 which is my account.
const GET_USER_BLOGS = `
query GetUserArticles($page: Int!) {
user(username: "hat52") {
publication {
posts(page: $page) {
title
brief
slug
dateAdded
coverImage
contentMarkdown
}
}
}
}
`;
GraphQL query to fetch data
I am fetching the following data for every blog post that I have posted on Hashnode.
brief: A brief description of the blog
title: Title of the blog
slug: A slug is the part of a URL that identifies a particular article on your blog and explains the page's content
dateAdded: Date when I posted the blog on Hashnode
coverImage: Cover image of the blog post
contentMarkdown: Get the content represented in markdown
Similarly, you can fetch other information about the blog. You can check the Hashnode API Playground to further explore the field that this API allows you to fetch. It allows you to build and try out your request first, and it has detailed documentation of the models available.
Advantages of using Hashnode API
Quick setup: Easily add a blog section to your portfolio website with the Hashnode API.
Powerful tools: Create rich, engaging content with Hashnode's text formatting, image, and code blocks.
Can handle traffic: With Hashnode's scalable infrastructure, your blog section can handle a large volume of readers.
Safe and secure: Your content is protected with Hashnode's security measures, keeping your blog section safe from cyber-attacks.
Customizable design: Personalize your blog section with custom branding, styles, and functionality.
Track success: Use Hashnode's analytics to see how your blog is performing and make informed content decisions.
Fetching Data
I have used the JavaScript fetch method to fetch the data from Hashnode. After fetching that data I will map the response to an interface I defined.
export const fetchBlogs = async () => {
let allBlogsFetched = false;
let page = 0;
const articles = [];
while (!allBlogsFetched) {
let response = await gql(GET_USER_BLOGS, { page: page });
articles.push(...response.data.user.publication.posts);
if (response.data.user.publication.posts.length === 0) {
allBlogsFetched = true;
}
page++;
}
return articles;
};
async function gql(query: string, variables = {}) {
const data = await fetch('https://api.hashnode.com/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query,
variables
})
});
return data.json();
}
Displaying the content
I am going to use hooks rather than the class component of React. To fetch the data from an API we need to call the API in useEffect. I Will use useState to manage the data fetched from API and to display it on the interface.
const [blogs, setBlogs] = useState<any>([]);
useEffect(() => {
const getBlogs = async () => {
const response = await fetchBlogs();
setBlogs(response);
};
getBlogs();
}, []);
Now After fetching the data I need to display it on the screen. For that I will use Array.prototype.map to iterate over the blogs array.
{blogs.map((data: any) => {
return <BlogCard data={data} />;
})}
In the above code snippet, I am returning the BlogCard component for every entry in the array and I am also passing the data object to the component.
Here is the card component that will display the blog. I have used tailwind CSS for styling the card component.
import { getDayMonth } from '@/utils';
export default function BlogCard({ data }: any) {
const date = getDayMonth(data.dateAdded);
return (
<div
className="rounded-[12px] h-max flex flex-col items-start gap-4 w-[80%] cursor-pointer">
<div className="rounded-[12px] relative header md:h-[300px] w-full overflow-hidden ">
<img
src={data.coverImage}
alt="a"
className="rounded-[12px] h-full w-full hover:scale-110 object-fit transition-all duration-500 ease-in-out transform "
/>
<p className="date flex flex-col items-center w-[40px] h-[50px] absolute right-4 top-10 p-1 rounded-[4px] text-white bg-cyanBlue">
<span>{date.day}</span>
<span>{date.month}</span>
</p>
</div>
<h5 className="uppercase hover:text-cyanBlue hover:scale-90 transition-all duration-500 hover:-translate-x-6 overflow-hidden truncate w-full text-white font-semibold ">
{data.title}
</h5>
<p className="text-white overflow-hidden truncate w-full">{data.brief}</p>
<button className="bg-cyanBlue px-4 py-2 text-white rounded-[50px]">Read More</button>
</div>
);
}
Result
Conclusion
If you have your portfolio website and you also write blogs then you must have your blog on your portfolio. It increases the user interactivity on your website and also you have another section to show the world.
Above I have explained one of the many ways to integrate blogs into your project. I have explained how we can use GraphQL to fetch data from Hashnode API. Then we looked into how we can call an API with the help of useEffect and how we can store data by using useState hook. After storing the data we needed to Iterate over it to display it on our interface for that we used Array.prototype.map.
Visit the finished site at hamzaa.dev (The site is in progress but you can visit the blog section which is complete).
If you have any suggestions please leave them in the comments.