From Jekyll to Astro: A Designer's Migration Journey

From Jekyll to Astro: A Designer's Migration Journey

After years running my portfolio on Jekyll, I finally pulled the trigger and migrated to Astro. As a designer who codes (or is it a developer who designs? I still can’t decide), I figured I’d document the process and share what I learned.

Why leave Jekyll?

Jekyll served me well. Really well, actually. My setup was solid:

  • Ruby-based static site generator
  • Liquid templating
  • Collections for portfolio and blog content
  • Tailwind CSS for styling
  • Cloudinary for images
  • Netlify for hosting

But over time, friction points started piling up:

1. Ruby dependency hell

Every time I wanted to make a quick edit—update a blog post, tweak some styles—I’d spend 20 minutes just getting my local environment running again. Ruby versions, gem conflicts, bundler updates…it got old fast.

2. Modern JavaScript felt bolted on

Jekyll handles basic JavaScript fine, but integrating modern frameworks or libraries? Clunky. I wanted better TypeScript support and wasn’t getting it.

3. Liquid templating limitations

Powerful enough for what it does, but restrictive compared to component-based approaches. I found myself writing repetitive code and fighting with complex data transformations.

4. Build times creeping up

Performance wasn’t terrible, but I wanted more control over bundle optimization and code splitting.

Why Astro?

I looked at the usual suspects—Next.js, Nuxt, SvelteKit. But Astro felt like the right fit.

✅ Zero JavaScript by default

Astro’s “islands architecture” means you only ship JavaScript when you actually need it. For a mostly-static portfolio? Perfect.

✅ Component-based everything

.astro files feel like JSX had a baby with HTML templating. Clean, intuitive, reusable:

---
const { title, excerpt } = Astro.props;
---

<article class="blog-card">
  <h3>{title}</h3>
  <p>{excerpt}</p>
</article>

✅ Framework agnostic

Use React, Vue, Svelte, or vanilla JavaScript as needed. You’re not locked in.

✅ Modern tooling

Built on Vite. TypeScript support out of the box. Hot module replacement. Fast builds. All the good stuff.

✅ Content collections

Type-safe frontmatter and better organization than Jekyll’s collections system:

// src/content/config.ts
export const collections = {
  blog: defineCollection({
    type: 'content',
    schema: z.object({
      title: z.string(),
      date: z.date(),
      excerpt: z.string(),
      tags: z.array(z.string()).optional(),
    }),
  }),
};

The migration process

1. Content migration

Moving from Jekyll’s _posts and collections to Astro’s src/content/ was straightforward:

Jekyll:

collections/
  _posts/
    2025-07-30-designing-for-scale-brighthr.md
  _portfolio/
    bubblebabysitting.md

Astro:

src/content/
  blog/
    designing-for-scale-brighthr.md
  portfolio/
    bubblebabysitting.md

Frontmatter mostly transferred directly, although I had to strip out Liquid-specific syntax.

2. Template conversion

This was the big one. Converting Liquid templates to Astro components:

Jekyll (Liquid):

{% for post in site.posts limit: 3 %}
  <article>
    <h3>{{ post.title }}</h3>
    <p>{{ post.excerpt | strip_html | truncate: 160 }}</p>
  </article>
{% endfor %}

Astro:

---
const posts = await getCollection('blog');
const recentPosts = posts.slice(0, 3);
---

{recentPosts.map(post => (
  <article>
    <h3>{post.data.title}</h3>
    <p>{post.data.excerpt}</p>
  </article>
))}

3. Data migration

Jekyll’s _data folder became src/data/, with YAML converted to JavaScript:

Jekyll (_data/tools.yaml):

design:
  title: "Design"
  items:
    - name: "Sketch"
      link: "https://sketch.com"

Astro (src/data/tools.js):

export const toolsData = {
  design: {
    title: "Design",
    items: [
      { name: "Sketch", link: "https://sketch.com" }
    ]
  }
};

4. Styling

Tailwind CSS transferred directly. The main change was switching from Jekyll’s asset pipeline to Vite’s handling of CSS and static assets.

Challenges (and how I solved them)

Challenge 1: TypeScript strictness

Astro’s TypeScript caught issues that Liquid had happily ignored.

Solution: Properly typed interfaces and content collection schemas. Annoying at first, but saved me from runtime errors.

Challenge 2: Build configuration

Moving from Jekyll’s _config.yml to Astro’s astro.config.mjs meant understanding Vite’s plugin system.

Solution: Started minimal, added features incrementally (Cloudinary integration, Tailwind, etc.).

Challenge 3: Deployment

Jekyll builds on Netlify were fire-and-forget. Astro required understanding Node.js build processes better.

Solution: Astro’s Netlify adapter handled most of it once configured properly.

Challenge 4: Content collection caching

During development, content changes sometimes didn’t show up immediately.

Solution: Delete the .astro cache when schemas change: rm -rf .astro

Performance improvements

The numbers don’t lie:

  • Build time: ~45 seconds → ~8 seconds
  • Bundle size: 40% smaller JavaScript bundles
  • Lighthouse score: 95 → 100 (Performance)
  • Hot reload: Near-instant vs 3-5 seconds

What I learned

Start with content

Migrate content first, build components around it. Kept my information architecture intact while modernizing the presentation.

Embrace components

Breaking Jekyll partials into proper Astro components improved reusability massively. Each component has clear props and responsibilities. No more spaghetti includes.

TypeScript is your friend

Even as a designer, TypeScript caught numerous mistakes. Content collection schemas especially—they catch frontmatter typos before they break your build.

Gradual enhancement

Astro’s islands let me add interactivity progressively. Contact modal, AOS animations, image zoom—all enhanced without tanking base performance.

The result

My Astro portfolio is:

  • Faster - Better performance, faster builds
  • 🛠️ More maintainable - Component architecture beats includes
  • 🔒 Type-safe - Fewer runtime explosions
  • 🚀 Future-proof - Modern tooling, active ecosystem

Should you migrate?

Consider Astro if:

  • You want better performance and modern tooling
  • Component-based architecture appeals to you
  • You need TypeScript support
  • You want framework flexibility
  • You’re comfortable with Node.js

Stick with Jekyll if:

  • You’re happy with Ruby/Liquid
  • Your site is simple and stable
  • You don’t need modern JavaScript features
  • Migration effort doesn’t justify the benefits

Resources I used

Migration took about two weeks of evening work. Worth it? Absolutely. Astro hits the sweet spot between static site simplicity and modern development experience.

Questions about migrating from Jekyll to Astro? Reach out—happy to help fellow designer-developers make the jump.

Let's build something that matters.

I'm currently open to Senior/Lead Product Designer, UX Designer and Service Designer roles - particularly in HR, Fintech, accessibility, or social impact.

Protected Content

This project is password-protected. Enter the password to view.