Table of Contents
Overview
In the previous post Social Share Automation Script, we covered social media share automation. In this final post of the series, we’ll compile the problems encountered during migration from Jekyll to Astro, their solutions, and useful tips.
During migration, you inevitably encounter unexpected issues not covered in the official documentation. We hope this post saves time for those going through a similar experience.
Mobile Horizontal Scroll Issue
Problem
After the migration, the site looked fine on desktop, but a horizontal scrolling issue appeared on mobile. Since testing was primarily done on desktop browsers, this went unnoticed for a while.
Cause
Originally, only overflow-x: hidden was set on <body>, but some mobile browsers (especially mobile Safari and certain Android browsers) don’t fully prevent horizontal scrolling with just that. It needs to be set on the <html> element as well.
Solution
The issue was resolved by adding overflow-x: hidden to the <html> element in src/styles/global.scss.
/* src/styles/global.scss */
html {
overflow-x: hidden;
}
body {
margin: 0;
overflow-x: hidden;
word-break: break-word;
letter-spacing: 0.8px;
background-color: #f6f8fa;
}
It’s a simple fix, but be aware that subtle horizontal scrolling can persist on mobile if you don’t set it on both html and body.
Additional Tip: Japanese word-break
There was an issue with line breaks not working properly in Japanese content. Since Japanese doesn’t use spaces between words, break-word alone doesn’t produce appropriate line breaks. This was resolved by applying a separate setting using the :lang(ja) selector.
/* src/styles/global.scss */
:lang(ja) body {
word-break: break-all;
}
Sass Deprecation Warnings
Problem
When importing SCSS files from Jekyll and building, a large number of deprecation warnings were output.
DEPRECATION WARNING: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
DEPRECATION WARNING: Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0.
Solution
Ideally, you would convert @import to @use/@forward and darken() to color.adjust(), but with the large volume of existing SCSS code, this wasn’t practical right away. As a first step, we silenced the warnings in the vite configuration in astro.config.mjs and planned a gradual transition to the new syntax.
// astro.config.mjs
vite: {
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ['import', 'global-builtin', 'color-functions'],
},
},
},
},
Here’s what each deprecation means:
| Deprecation | Description |
|---|---|
import | Recommends using @use/@forward instead of @import |
global-builtin | Recommends using module functions instead of global functions (darken() → color.adjust()) |
color-functions | Interface changes for color-related functions |
Shiki Code Highlighting
Differences from Jekyll
Jekyll used Rouge, a Ruby-based code highlighter, which required separate CSS file management. Astro has Shiki built in, so code highlighting works without any separate installation or CSS files.
Configuration
You only need to specify the theme in astro.config.mjs. I’m using material-theme-darker with a dark background.
// astro.config.mjs
markdown: {
shikiConfig: {
theme: 'material-theme-darker',
},
},
Comparison with Jekyll Rouge
Here’s a summary of the differences between the two approaches:
| Item | Jekyll (Rouge) | Astro (Shiki) |
|---|---|---|
| How it works | Generates HTML + CSS classes at build | Applies inline styles at build |
| Theme handling | Manage CSS file separately | Just specify the theme name in config |
| Language support | Depends on Ruby Gem | Uses VS Code-compatible grammar files |
| Configuration | _config.yml + CSS file | Single shikiConfig.theme line |
Since Shiki uses inline styles, there’s no worry about CSS file conflicts, and it provides the same level of syntax highlighting you see in VS Code.
Implementing Callouts with rehype-callouts
When writing blog posts, you sometimes need emphasis blocks like “Note”, “Warning”, or “Tip”. The rehype-callouts plugin allows you to easily use GitHub-style callout blocks in markdown.
Installation and Configuration
npm install rehype-callouts
// astro.config.mjs
import rehypeCallouts from 'rehype-callouts';
markdown: {
rehypePlugins: [
[rehypeCallouts, { theme: 'github' }],
],
},
Usage
In markdown, just put keywords like [!NOTE], [!TIP], [!WARNING] inside a blockquote.
> [!NOTE]
> Write reference content here.
> [!TIP]
> Write useful tips here.
> [!WARNING]
> Write cautionary content here.
It renders as callout blocks in the same style you see in GitHub READMEs. Since theme: 'github' is set, the colors and icons follow the GitHub style.
Handling External Links with rehype-external-links
Blog posts frequently include external site links, and for security and SEO, it’s good practice to add target="_blank" and rel="nofollow noreferrer" to external links. However, writing HTML directly in markdown every time is tedious.
The rehype-external-links plugin can automatically add these attributes to external links.
Configuration
// astro.config.mjs
import rehypeExternalLinks from 'rehype-external-links';
markdown: {
rehypePlugins: [
[rehypeExternalLinks, { target: '_blank', rel: ['nofollow', 'noreferrer'] }],
],
},
Effect
When you write an external link in markdown as usual:
[Astro official site](https://astro.build)
It is automatically transformed during the build to:
<a href="https://astro.build" target="_blank" rel="nofollow noreferrer"
>Astro official site</a
>
target="_blank": Opens in a new tab. The current blog page is preserved when clicking external linksrel="nofollow": Does not pass link weight to search enginesrel="noreferrer": Does not pass referrer information, improving security
This only applies to external links (https://...), not internal links (/en/astro/...), so you can write markdown as usual without any extra effort.
Migration Considerations
Here are the key things to watch out for when migrating markdown files from Jekyll to Astro.
1. permalink Format
In Jekyll, URLs are automatically generated from the permalink setting in _config.yml, but in Astro, you need to explicitly specify them in each post’s frontmatter. To preserve existing URLs, you must write the same URL pattern used in Jekyll.
# Jekyll: Auto-generated from pattern in _config.yml
permalink: /:categories/:title/
# Astro: Directly specified in each post's frontmatter
permalink: /astro/installation/
2. Date Handling
In Jekyll, frontmatter dates are automatically parsed, but in Astro’s Zod schema, you need to use z.coerce.date() to convert string dates into Date objects. Using z.date() will cause an error since it doesn’t accept strings.
// src/content.config.ts
// z.date() only accepts Date objects — causes error with string dates
// z.coerce.date() automatically converts strings to Date
date: z.coerce.date(),
3. published Field
We added a published field that didn’t exist in Jekyll. By setting default(true), existing posts without a published field automatically become public. Drafts are excluded from the build by specifying published: false.
// src/content.config.ts
published: z.boolean().default(true),
4. Image Paths
To keep the image paths used in Jekyll as-is, place images in the same structure within the public/ directory. Files in public/ are copied directly to dist/ during the build, so URLs remain unchanged.
# Jekyll: _site/assets/images/...
# Astro: public/assets/images/... → dist/assets/images/...
5. Removing Liquid Tags
Jekyll’s Liquid tags ({% raw %}{% include %}{% endraw %}, {% raw %}{{ }}{% endraw %}, etc.) are not processed by Astro and must be removed or replaced in the markdown.
{% raw %}{% include in-feed-ads.html %}{% endraw %}→<!-- ad -->(handled by the rehype-in-feed-ads plugin){% raw %}{{ site.url }}{% endraw %}→ Write the URL directly or handle it in a component
Final Performance Comparison
As we wrap up the series, here’s a comprehensive before-and-after comparison of the migration.
| Item | Jekyll | Astro |
|---|---|---|
| Full build time | ~209 seconds | ~30 seconds |
| Dev server startup | ~50 seconds (optimized) | ~2 seconds |
| File change reflect | Full rebuild | HMR instant update |
| Runtime dependency | Ruby, Bundler, Gem | Node.js, npm |
| Type safety | None | TypeScript + Zod |
| Image optimization | Plugin-dependent | Custom plugin based on Sharp |
| Code highlighting | Rouge + CSS file | Shiki (inline styles) |
| Search | Custom JSON-based | Pagefind (WebAssembly) |
| Sitemap | Plugin | @astrojs/sitemap |
| RSS | Plugin | @astrojs/rss |
| Comments | Utterances (same) | Utterances (same) |
Looking at the numbers, the ~7x improvement in build speed is the most striking, but the most impactful change in practice is the dev server. Compared to the days of waiting 50 seconds after editing a post, HMR with instant updates upon save is truly transformative.
Wrapping Up the Series
Through this series, we’ve shared the entire process of migrating from Jekyll to Astro. Here’s a summary of the full series:
- Why We Migrated from Jekyll to Astro — Build speed issues and the background for choosing Astro
- Astro Installation and Project Setup — Project configuration and directory structure
- Content Collections and Markdown Migration — Zod schema and content management
- Internationalization (i18n) Implementation — 3-language support system
- SEO Implementation — Meta tags, JSON-LD, sitemap
- Image Optimization — Custom rehype plugin
- Comment System (Utterances) — Lightweight comments based on GitHub Issues
- Ad Integration (Google AdSense) — AdSense integration and rehype plugin
- Implementing Search with Pagefind — Static search functionality
- Layout and Component Architecture — Component design
- GitHub Pages Deployment — Build and deployment pipeline
- Social Share Automation Script — Automated SNS sharing
- Troubleshooting and Tips
The migration from Jekyll to Astro started simply to improve build speed, but ultimately resulted in a significant improvement in the overall development experience. TypeScript support, Vite-based HMR, a flexible markdown plugin system, and integration with the modern Node.js ecosystem have made blog management much more enjoyable.
Migration isn’t always easy. There were many things to consider, such as converting existing content, maintaining URLs, and handling multilingual support. But once completed, blog operations become much smoother going forward.
We hope this series has been of some help to those considering a migration from Jekyll to Astro.
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku.Deku created the applications with Flutter.If you have interested, please try to download them for free.