Customize Your Blog with Hashnode's Headless Starter Kit
There are thousands of blogs on Hashnode, all with the same UI or format. So, how can you stand out? Focus on two things: "Content" and "Unique UI." While content can be improved, you can now also customize your blog using Hashnode's headless feature.
In this article, I will share my experience customizing my blog using Hashnode's Headless Starter Kit. I will walk you through the key components and steps I took to personalize my blog and make it stand out.
Let's start...
Use starter-kit
If you are familiar with GraphQL, you can build your blog from scratch using Hashnode's GraphQL APIs.
If you are a beginner or still learning things, you should use Hashnode's open-source blog starter kit, powered by Next.js and TailwindCSS.
Fork the repository and run the project locally. Just make sure you have Node.js installed on your system.
Let's understand the code
Before we customize our blog, we should familiarize ourselves with the code, shouldn't we?
So, there are two themes with ready-to-use blog functionalities:
Enterprise
Personal
I would recommend you go with the Personal theme because it is less complex than the Enterprise theme and would be easier to understand the code. Once you get comfortable with the code, you can add more components and functionality.
You don't need to grasp the entire code at once. There are merely two pages and a few components to understand in order to begin with basic customization.
Components
Personal Theme/Header (personal-theme-header.tsx): This component represents the header section of the blog. It displays the blog title, author's name, and navigation links to other pages or series of the blog.
container.tsx: The container component is a simple wrapper component that applies a max width container with margin auto to center the content.
cover-image.tsx: The cover-image component displays a responsive image that fills the width of its parent container and maintains a fixed aspect ratio also optionally linking them to posts, and supporting image preloading.
minimal-post-preview.tsx: This component displays a preview of a blog post with minimal information. It takes in a post title, date, slug, and comment count as props. It renders the title as a link to the post using the slug. It also displays the formatted date and comment count.
minimal-posts.tsx: This component gets a list of blog post details and shows a simple preview for each one. It uses the details (title, date, author, link, number of comments) to create a MinimalPostPreview for each post. This can be used on a main page to show blog post previews without loading the whole content.
Pages
Index (index.tsx): This is the main blog index page. It fetches initial posts and handles pagination. Displays posts using minimal-posts component. It also handles all the meta tags, social sharing tags, and SEO optimization for the publication home page. In simple words, it's the main landing page for our blog.
pages/[slug].tsx: This displays a single blog post page. It fetches the post data from GraphQL. It handles the post title, date, tags, cover image, content, SEO metadata, etc. Overall it's a reusable Post component to display a full blog post. In simple words, you are reading this article on [slug].tsx page.
tailwind-config.js: This is a Tailwind CSS configuration file, customizing colors, fonts, sizes, shadows and more for styling a site.
There are many more components and pages for tags, series, comments, and markdown styles. However, if you read and understand the code for the above-mentioned components and pages, that should be sufficient to get started with your customization.
How did I customize my blog?
After selecting the personal theme, I tried to understand it by modifying some parts of the code. To display blog post previews, I played around with the MinimalPostPreview component to understand how it renders condensed versions of each post.
And once I became comfortable with it, I made some changes step by step:
Customized the code to display minimal-preview posts as I wanted.
Added hero-post component
After looking at the code for the Enterprise theme, I got ideas for more improvements. I added a Table of Contents and comments to my post page.
I haven't made these changes to my actual blog yet because I still need to add features like audio blogs, post reactions, and social sharing. Once I learn more about Graphql and Hashnode's API, I'll be able to do that too.
Here is the customized blog -
Check out here -
How to Customize Your Blog
If you're still unsure, let's learn by making a few simple changes in the code.
First Step: Run the code locally, and you will see a blog page like this.
Open the component "minimal-post-preview". Remove the code from there, highlighted below.
..Then insert this new code there.
<div className="mh-400 w-full bg-slate-800 hover:bg-black">
<div className="p-4">
<h2 className=" font-custom text-xl leading-tight tracking-wide text-black hover:text-blue-400 dark:text-white">
<Link href={postURL}>{title}</Link>
</h2>
<br />
<p className="text-sm text-neutral-600 dark:text-neutral-400">
<DateFormatter dateString={date} />
</p>
</div>
</div>
Now you will see some changes in your blog's home page.
You can also choose how many posts to display in a minimal-preview.
By simply adding posts.slice(0, 2)
in your index.tsx file. Now minimal-preview will only show 2 posts.
Now that you understand how the minimal-post-preview works, let's create a new component for the Hero Post.
Create Hero Post Component
Create a new component called hero-post.tsx
and insert the code provided below.
import Link from 'next/link';
import { DateFormatter } from './date-formatter';
type Props = {
title: string;
coverImage: string;
date: string;
excerpt: string;
slug: string;
};
export const HeroPost = ({ title, coverImage, date, excerpt, slug }: Props) => {
const postURL = `/${slug}`;
const backgroundStyles = {
backgroundImage: `url(${coverImage})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
};
return (
<div className="sm-max:h-60 relative h-96 hover:opacity-90">
<div className="sm-max:h-50 absolute inset-0" style={backgroundStyles}></div>
<div className=" sm-max:bg-gradient-to-b sm-max:items-center absolute inset-0 flex bg-gradient-to-r from-black">
<div className="sm-max:w-full w-1/2 p-8 text-start text-white">
<h1 className="sm-max:text-2xl font-custom mb-4 text-4xl font-bold leading-tight tracking-wide sm:text-3xl md:text-5xl">
<Link href={postURL} className="hover:text-blue-400">
{title}
</Link>
</h1>
<div className="text-xl text-gray-300 md:text-2xl">
<Link href={postURL}>
<DateFormatter dateString={date} />
</Link>
</div>{' '}
<br />
<p className="sm-max:hidden lg-max:hidden text-sm text-neutral-600 dark:text-neutral-400">
<Link href={postURL}>
<span className="text-lg leading-snug text-slate-500 dark:text-neutral-400">
{excerpt.length > 140 ? excerpt.substring(0, 140) + '…' : excerpt}
</span>
</Link>
</p>
</div>
</div>
</div>
);
};
Now go to index.tsx
file and import HeroPost from hero-post.tsx
component
import { HeroPost } from '../components/hero-post';
then add the below code inside the container
{posts.length > 0 && (
<HeroPost
title={posts[0].title}
coverImage={posts[0].coverImage?.url || ''}
date={posts[0].publishedAt}
excerpt={posts[0].brief}
slug={posts[0].slug}
/>
)}
Just like this ⬇️
Great, now you have a hero post 🔥
Now let's extend the width of the container (in index.tsx
)
By adding 'max-w-screen-4xl'
, your hero post will look like this. Cool, isn't it?
However, don't forget to ensure responsiveness. In this case, I added some custom breakpoints as needed.
Go to tailwind-config.js
And add the below code there ⬇️
screens: {
'sm-max': { max: '639px' },
'sm-min': { min: '640px', max: '768px' },
'lg-max': { min: '640px', max: '1024px' },
},
Cool, now it's responsive for all devices.
That's how you can convert the personal theme into the blog of your dreams 🫡
I hope that by now, you have a clear understanding of the starter kit, including:
How to edit
what to edit
Refer to the code of the enterprise theme, so you will get a comprehensive idea of how to add more components.
Also, get help from-
Ensure that your code is optimized prior to integrating it with your actual blog.
And... That's it for today. See you soon in the next article.
Comments (2)
certainly applicable info here, once I have enough blog posts I can come back to this
Incredible blog, wow!