Migrating my blog from Gatsby to Astro

I recently switched my blog from Gatsby to Astro. Here’s what I did for that.


A few years ago, I launched my blog with Gatsby, one of the most popular static site generator built with React. Even the React documentation was built on top of it. Since I wanted my blog to be a playground for tech stack that I don’t use in my daily work, I started with Gatsby. Gatsby was great in many ways. It had its own rich ecosystem, with many plugins, built-in performance, and it was rather easy to start with. However it had some drawbacks. Whenever I wanted to do something, I had to follow the “Gatsby-way”. For example, when I added the dark color mode, I wanted to insert a script tag in my blog. To do that, I had to do some research and found that I had to add a callback function to the gatsby-ssr.js file using dangerouslySetInnerHTML. This felt tricky to me.

export const onRenderBody = ({ setHeadComponents }) => {
        __html: `
          // some function here.

Gatsby was also built in its own way, using GraphQL, Typography.js, own life cycle, etc.I did not tweak my blog much (just added dark mode, ToC and language button), but every time I did it was daunting.

Considering Alternatives

I was thinking to switch something else beside Gatsby. Initially, I considered switching to Next.js, but then Astro v1 came out, which sounded perfect to me.

Why Astro?

Astro is another static site generator with Zero JS by default, but you can include some JS with Component Islands architecture. (Btw, when I first saw the island architecture diagram, I felt very excited because I was experimenting with “micro-frontend” before, and even thought they are not quite the same, the concept diagram looked very similar at the first glance.) It supports .astro (its own DSL by default) which looks a bit weird at first but once you are used to it, it is not so bad because the format is similar to JSX. It also supports integration with many other frontend frameworks (such as React, Vue, Svelte and more). Astro seems to be simple but seems to be flexible enough with integrations so I switched to it.

Migration process

First, I learned Astor by following the tutorial, which was very comprehensive. Then, I began a new project by using the migrating guide. It was mostly straightforward, and documentation was very well, but I needed to make a few additional tweaks. I may write a separate blog posts for each topic, but here is a summary what I did:


The Astro documentation itself is an excellent example project that you can use as a reference.

Code block with title

You can write code block by using triple backquotes, but if you wanted to add title to it, you need to make a tweak. Gatsby has a plugin for that, so I wanted to something similar. Luckily, Astro is doing the exact thing on the docs, which is written as an integration. So, I ported it from there. It is written as a remark plugin to parse the title from the code block and embed the corresponding component by using astro-auto-import. The supported syntax is:

```js title="example.js"


The original plugin supports code highlight as well, but I have not used it in my blog so far, so I did not import it.


Astro provides the image integration. The image can be stored in several locations, but I chose to save the same directory with markdown file and use mdx import because I wanted to save them close to the markdown file rather than saving them in public/assets/.


I am using Google Analytics in this blog. To install it, I use partytown integration. Partytown is a library to move intensive script off of the main thread by using web worker. I have only heard about it and did not know when to use it. Now I know the one of the best use cases.

Twitter card / oEmbed

Gatsby has a plugin called gatsby-remark-embedder to embed third-party contents (such as Twitter and YouTube) to a blog. It will parse the Twitter URL in the markdown content and convert it to iframe automatically to embed the content.

To achieve this, I picked @remark-embedder/core and @remark-embedder/transformer-oembed. It does the same thing as the Gatsby plugin because it was extracted from it. The transformer implementation is very clean with the power of oEmbed. I used to have my own SpeakerDeck component, but I finally abandoned it because SpeakerDeck also supports oEmbed.

They are implemented as remarkPlugin, so the installation is like this:

import remarkEmbedder from '@remark-embedder/core';
import oembedTransformer from '@remark-embedder/transformer-oembed';

// To use twitter's widget.js, you have to wrap by <div></div> to work with @remark-embedder/core.
function handleHTML(html, info) {
  const { url, transformer } = info;
  if (
    transformer.name === '@remark-embedder/transformer-oembed' ||
  ) {
    return `<div style="max-width: max-content; margin-left: auto; margin-right: auto">${html}</div>`;
  return html;

// https://astro.build/config
export default defineConfig({
  site: 'https://nobuhikosawai.com/',
  markdown: {
    remarkPlugins: [
          transformers: [oembedTransformer],

Design - tailwind and darkmode

I also redesigned my blog (and probably spent the most time on this.). For this work, I used Tailwind CSS which made the process much easier thanks to its pre-picked color token. In my previous blog, I had to manually select all the colors, but Tailwind made it simpler and the result looks better than the last one.

To design the markdown content, I used @tailwindcss/typography, which is beautifully designed, especially for text content. However, this plugin has a strong style, so I recommend to only apply it to the text content. Initially, I applied it to my entire blog to short-cut the designing process and used not-prose class to undo the style when I don’t want to apply. But I later realized that I was using not-prose too often and stopped using it anything other than text.

My previous blog had a dark mode, so I implemented again this time. I used the animated theme switcher from toggles.dev to add nice animation. This web.dev article was very helpful in implementing the dark mode feature.


All in all, Astro is great and perfect match for my blog. The migration process from Gatsby to Astro is relatively straightforward, and the Astro documentation is a great resource for reference. With a few tweaks and integrations, you can customize your Astro blog to your liking. Now that I have refreshed my blog, I am excited to write more content here.

(Note: The content of this text has been written by me, but brushed up with the assistance of Chat GPT-3 to improve the clarity and accuracy of my English.)