How I Built My Personal Blog with Astro and Hashnode


📝 Introduction
As a developer, I’ve always wanted a personal space on the web — a place to share what I’m learning, document side projects, and write about things that interest me. After trying out a few blogging platforms, I realized I wanted something more flexible and customizable — something I could truly call my own.
That's when I decided to build my personal blog using Astro and Hashnode.
My goal was to create a fast, modern blog that’s easy to maintain, but also allows me full control over the design and structure. I wanted to write posts in a comfortable interface, without having to manually push Markdown files or commit content changes to Git.
So I chose:
Astro for its blazing-fast static site generation and component-based architecture
Hashnode as a headless CMS, to manage and write articles with ease
TailwindCSS for rapid and responsive styling
In this article, I’ll walk you through how I built and deployed the blog, how I connected it to Hashnode, and how I automated content updates using webhooks — all with a clean and minimal setup.
✨ Why Astro?
Astro stood out to me for a few key reasons:
Static by default: Astro generates static HTML at build time, making the blog super fast and SEO-friendly.
Framework flexibility: It supports React, Vue, Svelte, Solid, or even no framework at all. You use components only when you need them.
Zero JS by default: Astro ships zero JavaScript unless you explicitly add it, keeping the site lightweight.
Markdown + MDX support: Writing in Markdown feels natural, but MDX support means I can also embed components in blog content if needed.
With Astro, I got full control over routing, layouts, and performance without sacrificing simplicity.
🚀 Why Hashnode as a Headless CMS?
I chose Hashnode for content management because:
It has a beautiful writing interface with support for Markdown.
It's free to use and doesn't restrict API access.
Every article has a public API, accessible via a simple GraphQL endpoint.
No content lock-in — I can move anytime and fetch my data freely.
Most importantly, it separates content creation from frontend development. I can focus on writing in Hashnode and let Astro handle the rendering.
🚪 Project Setup
Here’s how I bootstrapped the project:
Create a new Astro project:
npm create astro@latest
Choose the blog template or start from scratch.
Install TailwindCSS
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
Then configure
tailwind.config.cjs
and include Tailwind insrc/styles/global.css
.Clean up the template and create components like
Layout.astro
,PostCard.astro
, etc.
🔍 Fetching Articles from Hashnode
Hashnode offers a public GraphQL API. I used this to fetch my published articles:
Setup a simple
fetchPosts
function:const response = await fetch('https://gql.hashnode.com', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: `{ publication(host: "your-hashnode-blog.hashnode.dev") { posts(page: 0) { title brief slug coverImage dateAdded } } }` }) });
Display posts using an Astro component loop.
🌐 Creating Individual Blog Post Pages
Astro's file-based routing and getStaticPaths
let you generate pages dynamically:
Create
[slug].astro
undersrc/pages/blog/
Use
getStaticPaths()
to prebuild pages based on each post slugFetch full article data using the same GraphQL API
Render post content using Astro markdown rendering or HTML from the API
You can also set metadata like <title>
, <meta description>
, and OpenGraph tags dynamically.
♻️ Automating Deployment
One downside of using SSG is that new articles don't appear until you rebuild the site. To solve this:
I deployed my blog to Vercel (Netlify works too).
I created a Deploy Hook in the Vercel dashboard.
I connected Hashnode to trigger that hook via a webhook (using Zapier or a simple webhook service).
Now, every time I publish on Hashnode, my blog auto-rebuilds and deploys the updated content.
⚡ Challenges I Faced
SSG Limitations: Initially, I was confused why new posts weren’t showing. Understanding how static builds work helped me fix that with deploy hooks.
GraphQL Pagination: Hashnode paginates results, so for lots of posts, you need to implement pagination logic.
Image hosting: Some cover images from Hashnode had CORS issues or broken links; I added fallbacks and lazy loading.
🤝 Future Improvements
Here are a few enhancements I plan to add:
Search functionality using Fuse.js or Algolia
Tag/category filtering for better navigation
RSS feed and newsletter integration
Optionally switch to SSR if I ever need real-time content rendering
📄 Conclusion
Building my blog with Astro and Hashnode was a fun and rewarding experience. I got the best of both worlds: Astro gives me total control over the frontend and performance, while Hashnode takes care of content management with a great writing UX.
If you're looking to build a developer blog that's fast, easy to manage, and future-proof, I highly recommend this stack.
Subscribe to my newsletter
Read articles from Taufik Rahadi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Taufik Rahadi
Taufik Rahadi
Hey there! I'm your friendly neighborhood software engineer, fueled by strong coffee, epic tunes, and an unending quest for clean code (and cat cuddles, obviously). When I'm not busy wrangling GraphQL, REST, gRPC, and microservices into submission, you can usually find me whipping up something delicious in the kitchen for my amazing wife or diving headfirst into the wild world of AI. I'm all about pushing the boundaries of what's possible in tech and sharing every 'aha!' moment along the way. Stick around, it's gonna be a fun ride.