Skip to content

A new website - Jekyll to Astro Starlight migration

Back in 2021 I made the choice to use a Jekyll template as an alternative to Obsidian Publish. And now, a few years later, it was time to take the next step. There were some bugs in the Jekyll website and I wanted, among other things:

  • a dark theme
  • a search function
  • more functionality, such as Tabs, Steps and Code components
  • to retain markdown notes (posts)
  • to keep the workflow with the Github repository and build functionality via Cloudflare
  • to retain the graph view and backlinks components
  • to keep the comments functionality via Github

After a long search, I finally made the decision to migrate from Jekyll to Astro Starlight with plugins like blog, site-graph). My workflow would change: I would no longer create notes (posts) using Obsidian but with VSCodium (VS Code) using the MDX syntax and plugin. Below are the steps I followed on Debian Linux.

  1. Install git if you want to initialize a new git repository (recommended), for example:

    # Open your terminal application
    sudo apt-get update && sudo apt-get install git
    # Add your username and e-mail for all repositories or run from a specifiek repository location without --global
    git config --global user.name "Your Name"
    # Check with git config --get user.name
    git config --global user.email "[email protected]"
    # Check with git config --get user.email
  2. Install Node.js for example by using the Node Version Manager

    # Open your terminal application
    # Download and install nvm
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
    # Restart the shell
    \. "$HOME/.nvm/nvm.sh"
    # Download and install Node.js:
    nvm install 24
    # Verify the Node.js version:
    node -v # Should print the Node.js version
    # Verify npm version:
    npm -v # Should print the npm version
  3. Install Visual Studio Code or VSCodium. VSCodium is VS Code but without Microsoft branding/telemetry/licensing and you can for example use extrepo:

    # Open your terminal application
    sudo apt-get update && sudo apt-get install extrepo
    sudo extrepo enable vscodium
    sudo apt-get update && sudo apt-get install codium
    # Install the Astro and MDX extensions
    codium --install-extension astro-build.astro-vscode
    codium --install-extension unifiedjs.vscode-mdx
  1. Go to the terminal and create a folder, for example: mkdir ~\starlight

  2. Go to the folder, for example: cd ~\starlight

  3. Create a new project: npm create astro@latest -- --template starlight

    • Where should we create your new project (type in): ./fictionbecomesfact for example
    • Do you plan to write TypeScript: yes
    • How strict should typescript be: Strict (recommended)
    • Install dependencies: Yes
    • Initialize a new git repository: Yes

    The project has now been created. Read more about the project structure here

  4. I personally prefer to disable telemetry: npm run astro telemetry disable

  5. Next, I added the following integrations and plugins:

  6. Enter your project directory using cd fictionbecomesfact and run npm run dev to start the dev server or npm run astro build to build and to preview npm run preview. Now you can visit your site by browsing to: http://localhost:4321/. Use CTRL+C to stop.

I modified the config.ts file as follows:

src/content/config.ts
import { defineCollection, z } from 'astro:content';
import { docsSchema } from '@astrojs/starlight/schema';
import { docsLoader } from '@astrojs/starlight/loaders';
import { pageSiteGraphSchema } from 'starlight-site-graph/schema';
import { blogSchema } from 'starlight-blog/schema';
export const collections = {
docs: defineCollection({
loader: docsLoader(),
schema: docsSchema({
extend: (context) => blogSchema(context),
})
}),
};
// Extend the built-in schema
docsSchema({
extend: pageSiteGraphSchema
})
docsSchema({
extend: z.object({
// Add a new optional field to the schema.
comments_id: z.number().optional(),
}),
})

The necessary adjustments are made so that all plugins work and I added the comments_id field so that I can specify it in the frontmatter of a post which comments (GitHub issue) belong to the post.

Ultimately, my astro.config.mjs file looks like this:

./astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import starlightSiteGraph from 'starlight-site-graph';
import starlightBlog from 'starlight-blog';
import mdx from "@astrojs/mdx";
import rehypeSlug from 'rehype-slug';
export default defineConfig({
site: 'https://www.fictionbecomesfact.com',
redirects: {
'/digitalgarden': '/notes/digitalgarden'
},
build: {
inlineStylesheets: 'always'
},
markdown: {
rehypePlugins: [
rehypeSlug,
],
},
integrations: [
starlight({
title: "Fiction Becomes Fact",
logo: {
light: '/src/assets/fbf-banner-light.webp',
dark: '/src/assets/fbf-banner-dark.webp',
replacesTitle: true,
},
favicon: '/images/favicon.png',
head: [
// Add ICO favicon fallback for Safari.
{
tag: 'link',
attrs: {
rel: 'icon',
href: '/images/favicon.ico',
sizes: '32x32',
},
},
{
tag: 'script',
attrs: {
src: '/scripts/showdown.min.js',
defer: true,
},
},
],
credits: false,
lastUpdated: false,
social: [
{
label: 'GitHub',
icon: 'github',
href: 'https://github.com/fictionbecomesfact',
},
],
customCss: [
'./src/styles/global.css' ,
'./src/styles/fontawesome.all.min.css',
'./src/styles/comments.scss',
'./src/styles/headings.css'
],
sidebar: [
{
label: "leadingNavLinks",
items: [
{ label: "Tech Notes", link: "/notes" },
],
},
],
components: {
Footer: './src/overrides/Footer.astro',
LastUpdated: './src/overrides/LastUpdated.astro',
},
plugins: [
starlightBlog({
title: '',
prefix: 'notes',
metrics: {
readingTime: true,
//words: 'total',
},
}),
starlightSiteGraph(),
],
}), mdx()],
devToolbar: { enabled: false },
});

The above gives an idea of what you can configure. In this way, for example, I use custom CSS and have customized the footer through an override. It is also easy to add a script like Showdown to the head. Furthermore, I have changed the default prefix blog of the Starlight Blog plugin to notes.

My custom footer with the copyright:

src/overrides/Footer.astro
---
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
import Default from '@astrojs/starlight/components/Footer.astro';
const starlightRoute = Astro.locals!.starlightRoute as StarlightRouteData;
const siteTitle = starlightRoute?.siteTitle ?? '';
const pathname = Astro.url.pathname;
const hideFooter = [
pathname === '/' || pathname === '',
pathname === '/notes' || pathname === '/notes/',
pathname.startsWith('/notes/tags/virtualisation'),
pathname.startsWith('/notes/tags/development'),
pathname.startsWith('/notes/tags/linux'),
pathname.startsWith('/notes/tags/workflow'),
pathname.startsWith('/notes/tags/databases'),
pathname.startsWith('/notes/tags/smarthome'),
pathname.startsWith('/notes/tags/ai'),
pathname.startsWith('/notes/tags/networking'),
].some(Boolean);
const currentYear = new Date().getFullYear();
---
{hideFooter ? (
<footer></footer>
) : (
<>
<Default {...Astro.props}>
<slot />
</Default>
<span class="copyright" role="contentinfo">
<i class="fa fa-copyright" aria-hidden="true"></i>&nbsp;Copyright 2021-{currentYear}&nbsp;{siteTitle}
</span>
</>
)}
<style>
.copyright {
display: inline-flex;
align-items: center;
gap: 0.5em;
margin: 1.5rem auto;
font-size: var(--sl-text-xs);
color: var(--sl-color-gray-3);
text-decoration: none;
}
</style>

Now you can create posts in the /src/content/docs/blog (or src/content/docs/notes in my case) by adding .md or .mdx files. Here is a MDX example with a full frontmatter, some text and the custom comments component:

src\content\docs\notes\jekyll-astro-starlight-migration.mdx
---
title: A new website - Jekyll to Astro Starlight migration
description: The website has been updated and I have chosen to replace Jekyll with Astro Starlight
date: 2025-02-10
lastUpdated: 2026-03-09
tags:
- Development
- Workflow
excerpt: The website has been updated and I have chosen to replace Jekyll with Astro Starlight.
featured: false
draft: false
slug: notes/jekyll-astro-starlight-migration
#cover:
# alt: A beautiful cover image
# image: ../../../assets/houston.webp
graph:
visible: true
backlinks:
visible: true
comments_id: 77
---
import Comments from '../../../components/Comments.astro';
import { Icon, LinkCard, CardGrid, Code, Tabs, TabItem, Badge, Steps } from '@astrojs/starlight/components';
## Hello
Hello world!
## <span id="favorites" style="display: inline-flex; gap: 8px"><Icon name="external" /> Favorites</span>
<CardGrid>
<LinkCard title="Astro Starlight Docs" href="https://starlight.astro.build/getting-started" target="_blank"/>
</CardGrid>
## <span id="comments"><i id='mdx-icon' class='fa fa-comments' style="text-decoration: none"></i> Comments</span>
<Comments is:raw comments_id={frontmatter.comments_id} />

    No comments found for this note.

    Join the discussion for this note on Github. Comments appear on this page instantly.

     Copyright 2021-2026 Fiction Becomes Fact