Building a blog with Astro - Code editor showing Markdown files, Astro logo, and technical architecture diagrams
web_development

How I Built This Blog with Astro: A Developer's Behind-the-Scenes Journey

Discover the technical decisions and implementation details behind building a modern blog with Astro, Markdown posts, and custom frontmatter structure.

7 min read

You know that feeling when you're trying to explain something technical to a friend, and suddenly you realize you've been overcomplicating it? That's exactly what happened when I decided to build this blog. I wanted something simple, fast, and easy to maintain – but also flexible enough to grow with my ideas.

After trying several approaches (and yes, I went down a few rabbit holes), I landed on Astro. And honestly? It's been one of those rare "just works" experiences that makes you wonder why you didn't try it sooner.

Why I Chose Astro Over Everything Else

Let me be real with you – the static site generator landscape is overwhelming. There's Gatsby, Next.js, Nuxt, Jekyll, Hugo... the list goes on. Each one promises to be the solution to all your problems, but most come with their own set of headaches.

Here's what I needed:

  • Lightning-fast performance (because life's too short for slow websites)
  • Markdown support (I want to write, not fight with editors)
  • Zero JavaScript by default (let's keep things lean)
  • Easy deployment (one-click would be nice)
  • Developer experience that doesn't make me want to scream

Astro checked every box. It's like finding that perfect coffee shop – you know it when you experience it.

The Magic Behind the Scenes

Project Structure That Actually Makes Sense

Here's how I organized everything:

PersonalProfile/
β”œβ”€β”€ _posts/           # English blog posts
β”œβ”€β”€ _posts_es/        # Spanish blog posts  
β”œβ”€β”€ public/
β”‚   └── images/blog/  # SVG illustrations
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/   # Reusable Astro components
β”‚   β”œβ”€β”€ layouts/      # Page templates
β”‚   └── pages/        # Dynamic routes
β”œβ”€β”€ astro.config.mjs  # Astro configuration
└── package.json      # Dependencies

Simple, clean, and intuitive. No weird nested folders or confusing conventions.

The Heart of It All: Markdown with Superpowers

Each blog post is just a Markdown file with some special sauce at the top called "frontmatter." Think of it as metadata that tells Astro how to handle each post:

---
title: "Your Awesome Post Title"
categories: web_development
tags: ["astro", "markdown", "tutorial"]
date: "2025-06-23"
description: "A compelling description for SEO and previews"
featured_image: "/images/blog/your-post-image.svg"
featured_image_alt: "Descriptive alt text for accessibility"
---

# Your actual content starts here...

This frontmatter is like a business card for each post. It tells Astro:

  • What the post is about (title and description)
  • When it was published (date)
  • How to categorize it (categories and tags)
  • What image to show (featured_image)
  • How to make it accessible (alt text)

Dynamic Routing: The Secret Ingredient

Here's where Astro really shines. I created a dynamic route that automatically generates pages for all my blog posts:

// src/pages/blog/[slug].astro
---
import Layout from '../../layouts/Layout.astro';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { marked } from 'marked';

export async function getStaticPaths() {
  const postsDirectory = path.join(process.cwd(), '_posts');
  const filenames = fs.readdirSync(postsDirectory);
  
  return filenames
    .filter(name => name.endsWith('.md'))
    .map(name => ({
      params: { slug: name.replace('.md', '') }
    }));
}

const { slug } = Astro.params;
const postsDirectory = path.join(process.cwd(), '_posts');
const fullPath = path.join(postsDirectory, `${slug}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data: frontmatter, content } = matter(fileContents);
const htmlContent = marked(content);
---

<Layout title={frontmatter.title}>
  <article>
    <h1>{frontmatter.title}</h1>
    <div set:html={htmlContent} />
  </article>
</Layout>

This single file creates individual pages for every Markdown file in my _posts folder. Write a new post, save it, and boom – you have a new page with a clean URL like /blog/my-awesome-post.

Bilingual Support Without the Headache

Since I write in both English and Spanish, I needed a clean way to handle multiple languages. My solution? Separate folders and routing:

  • English posts go in _posts/
  • Spanish posts go in _posts_es/
  • Each has its own dynamic route (/blog/[slug].astro and /blog-es/[slug].astro)

This keeps things organized and makes it easy to maintain both versions without getting confused.

The Performance Story

One of the things that constantly amazes me about Astro is how fast everything loads. Here's why:

Zero JavaScript by Default

Astro doesn't ship any JavaScript to the browser unless you explicitly need it. Your blog posts are pure HTML and CSS – which means they load instantly and work even with JavaScript disabled.

Smart Asset Optimization

Images get optimized automatically, CSS gets minified, and unused styles get purged. It's like having a personal performance coach that works 24/7.

Build-Time Generation

Everything gets pre-built during deployment. When someone visits your site, they're getting pre-generated HTML files – no server-side rendering delays.

Real-World Benefits I've Experienced

Writing Is Actually Enjoyable

No more fighting with WYSIWYG editors or complex publishing workflows. I write in Markdown, git push, and the site updates automatically.

Maintenance Is Minimal

No database to backup, no security updates to worry about, no server to maintain. The whole site is just files that can be hosted anywhere.

Loading Speed Is Addictive

Seeing those green Lighthouse scores never gets old. Fast sites aren't just nice to have – they're essential for user experience and SEO.

Deployment Is Effortless

Connected to GitHub, deployed on Vercel. Push to main branch, and the site updates automatically. It's the kind of workflow that makes you wonder why everything can't be this simple.

Lessons Learned Along the Way

Start Simple, Add Complexity Later

I initially wanted to add comments, search, analytics, and a dozen other features. Starting with just the blog and adding features incrementally was the right call.

Markdown + Frontmatter Is Powerful

This combination gives you the writing experience of a simple text editor with the power of a full CMS. It's like having your cake and eating it too.

Performance Matters More Than You Think

A fast site isn't just about vanity metrics. It affects everything – user experience, SEO rankings, conversion rates, even your own motivation to maintain the site.

Developer Experience Affects Everything

When it's easy and enjoyable to add content, you actually do it. When it's a pain, your blog becomes a digital graveyard.

What's Next?

I'm planning to add:

  • Search functionality (probably with Algolia or a simple client-side solution)
  • Reading time estimates
  • Related posts suggestions
  • RSS feed for subscribers
  • Comment system (maybe with Giscus)

The beauty of this setup is that I can add any of these features without rebuilding everything from scratch.

Want to Try This Yourself?

If this approach sounds appealing, here's how to get started:

  1. Install Astro: npm create astro@latest
  2. Add Tailwind (optional but recommended): npx astro add tailwind
  3. Create your first post in a _posts folder
  4. Set up dynamic routing following the pattern I showed above
  5. Deploy to Vercel or Netlify with GitHub integration

The whole setup can be done in an afternoon, and you'll have a blog that's fast, maintainable, and enjoyable to work with.

Final Thoughts

Building this blog with Astro has been one of those rare projects where the tool just gets out of your way and lets you focus on what matters – creating content that people actually want to read.

If you're thinking about starting a blog or migrating from another platform, I'd seriously consider this approach. It's simple enough for beginners but powerful enough to grow with your needs.

And hey, if you have questions about the implementation or want to see something specific, drop me a line. I'm always happy to talk shop with fellow developers.

Happy coding! πŸš€


This entire blog is open source and available on GitHub at https://github.com/jvillu/PersonalProfile. Feel free to fork it, modify it, or just poke around to see how everything works together.

Javier Villullas

Javier Villullas

AI-First Azure Cloud Expert

With over 20 years of experience in software development, I specialize in building intelligent cloud solutions that leverage AI to drive real business value. I help organizations transform their operations through AI-first architecture and Azure cloud technologies.

Back to Blog

More AI & Cloud Insights

Explore more articles about artificial intelligence, cloud architecture, and modern development practices.

View All Posts