Why I Migrated My Blog from Pelican to Quarto
For years, my blog ran on Pelican, a static site generator written in Python. It was powerful, flexible, and a constant source of frustration. I found myself spending more time wrestling with configurations, fixing broken themes, and making sacrifices to the dependency gods than actually writing.
I wanted a change, and I wanted a tech stack that would let me focus on content creation, not on web design and endless config files. I wanted something self-hosted (f*ck off, Medium1), data science-friendly, and straightforward to maintain.
So while I was browsing some random statistics blog, I was very lucky to rediscover Quarto from my R days!
What is Quarto? And Why Leave Pelican?
I first stumbled upon Quarto while looking for better ways to create slide decks from my Jupyter notebooks. It’s an open-source scientific and technical publishing system developed by the team behind RStudio (now Posit). It’s built on Pandoc and allows you to create dynamic content with Python, R and Julia.
It’s fantastic for presentations and reports, but it’s also designed to build entire websites.
So, why did I finally ghost Pelican?
- Config and Dependency Hell: Pelican is flexible, but that flexibility comes at the cost of complex configuration files. Setting up themes, plugins, and even basic metadata felt like a chore. Pelican seemed to be in a constant feud with my other dependencies.
- Convoluted Workflow: My writing process involved a series of clunky steps to convert my notebooks, manage static assets, and preview changes. It was anything but seamless.
- Unmaintained and Broken Themes: The theme I was using became unmaintained. My attempts to customize it led to a cascade of broken CSS and Jinja2 template errors. Web dev is definitely not my strong suit.
Quarto gives me a solution to all these issues with its “convention over configuration” philosophy and makes it incredibly easy to get started and maintain.
Getting Started
One of the bests parts of moving to Quarto was the setup. Creating a fully functional blog is literally a one-line command:
quarto create-project my-awesome-blog --type website:blog
This single command scaffolds a complete blog structure for you, with sample posts, an index page, and an about page.
Writing Your First Post
You can write your posts directly in the formats you already know and use:
- Jupyter Notebooks (
.ipynb
): This is a game-changer for data scientists. You can write your analysis, generate plots, and write your narrative all in one place. To make a notebook a blog post, you just need to add a raw cell at the very top with the YAML frontmatter. - Quarto Markdown (
.qmd
): This is a superset of Pandoc Markdown. It’s clean, simple, and allows you to embed executable code chunks from Python, R, and more, right within your markdown file.
All your posts go into the posts/
directory. Here’s an example of the YAML frontmatter you’d put in a raw cell at the top of a Jupyter Notebook or at the top of a .qmd
file:
---
title: "My First Quarto Post"
author: "Your Name"
date: "2025-07-21"
categories: [Python, Data Science, Quarto]
image: "preview.png"
---
I like to create a new Git branch for every new post, which keeps your main branch clean and makes it easier to manage drafts.
git checkout -b new-post-on-quarto
git commit -am "feat: add new post on quarto"
git push origin new-post-on-quarto
# Create a pull request to merge into main when ready
Theming and Customization
The Bootstrap out-of-the-box styling makes customization intuitive for anyone with basic web knowledge, or even less than basic like me. You can easily tweak colors, fonts, and layouts using a simple .scss
file. In your project’s root, just create a file named theme.scss
and reference it in your _quarto.yml
file.
You can use Bootstrap’s components like cards or alerts to make your documents more engaging and professional.
# _quarto.yml
project:
type: website
website:
title: "My Awesome Blog"
theme:
light: cosmo
dark: darkly
# Or for custom themes:
# light: theme.scss
Hosting and Deployment
Quarto produces a static website that you can host anywhere, with one of the most popular (and free) options being GitHub Pages, although there are probably others like Netlify.
Essential Features
Setting up features that were cumbersome in Pelican is trivial in Quarto.
- RSS Feed: Just add a few lines to
_quarto.yml
. Quarto handles the rest. - Comments: You can easily integrate services like Giscus (which uses GitHub Discussions), Utterances, or Hypothesis. For Giscus, you add a
comments
section to your_quarto.yml
. - Analytics: Add your Google Analytics tracking ID or, for a more privacy-focused option, use a service like Umami. It’s just another simple addition to the main config file.
- Other Cool Stuff: One of my favorite features is “listings.” You can group posts by category or even create a dedicated series. By adding a
series
tag to your post’s frontmatter, Quarto can automatically generate a listing page that groups these posts together, showing the reader what else is in the series.
Takeaway: Focus on What Matters
Migrating my blog to Quarto has felt liberating. I actually put it off for a long time because I dreaded the process, but once I got to it a year later, I was done in a couple of hours.
The entire system is designed to be intuitive and stay out of your way. Writing posts directly in Jupyter notebooks has streamlined my workflow immensely, while style supporting enhanced Markdown for simpler articles. I now spend my time thinking about content, code, and analysis instead of why my theme’s CSS is broken again.
If you’re a technical professional who wants to run a blog without much hassle, I can’t recommend Quarto enough. It’s the simple, powerful, and data-science-aware tool I wish I had from the start.
Footnotes
Medium is heavily paywalled, which contradicts the movement towards open science and reproducibility. Their revenue model also disincentivizes concise and technical writing. It’s basically SEO bait for scientific writing, padded with repetitive phrasing and buzzwords designed to artificially maximize reader engagement and time.↩︎