Migration gallery: four real blogdown sites, four themes

How does migrate_hugo() behave on real sites – not toy fixtures, but blogdown sites that shaped the R community, with a decade or two of posts, theme-specific menus and hand-tuned layouts? This vignette migrates four published blogdown/Hugo sites, one to each supported theme, and shows the result side by side with the original.

Site Author Hugo theme Migrated to
yihui.org Yihui Xie (knitr, blogdown) hugo-paged minima
juliasilge.com Julia Silge (tidymodels) Academic Chirpy
jennybryan.org Jenny Bryan (tidyverse) hugo-theme-sam Minimal Mistakes
allanvc.github.io Allan Quadros hugo-researcher al-folio

Each migration ran on the site’s public source repository, unmodified (migrate_hugo() never writes into the source). The “before” screenshots come from the published sites (for Julia Silge’s, whose live site has since moved to Quarto, from the Internet Archive’s snapshot of the blogdown era); the “after” screenshots are the migrated sites built locally with build_site(), with no cosmetic fixes between the migration and the screenshot (the single deviation is disclosed in Julia Silge’s section). All content shown belongs to its authors and appears here, with links to the originals, only to illustrate the migration.

One option matters for sites like these:

migrate_hugo(from, to, theme = ..., rerender = FALSE)

rerender = FALSE migrates the rendered Markdown that blogdown committed next to each .Rmd/.Rmarkdown source, instead of queueing the sources for re-knitting – the right choice for an archive, where code from 2008 should not run again in 2026.

Yihui Xie to minima

The creator of knitr and blogdown, and 19 years of posts:

migrate_hugo("yihui.org", "yihui-minima", theme = "minima",
             only_referenced = TRUE, rerender = FALSE)
#> v 1884 posts migrated

1884 posts came through, Jekyll built all of them, and the spirit of the original – radical minimalism – survives in minima:

yihui.org before (Hugo, left) and after (minima, right)

The stress test hiding in this site: posts about LaTeX and templating contain literal {{ sequences, which Jekyll’s Liquid engine treats as template tags – one such post aborts the entire 1884-post build. migrate_hugo() escapes them automatically (your own {{ site.baseurl }} links are left alone):

“The Best Way to Support LaTeX Math in Markdown”: the same post on hugo-paged (left) and after migration, on minima (right)

What stayed manual, from the migration report: yihui.org is bilingual, and both languages land in one post feed (per-language sites need curation).

One more thing a statistician’s archive needs: minima ships no MathJax, so LaTeX math renders as raw text. One call fixes it – theme-aware, so the same function flips al-folio’s native flag, enables Chirpy’s per-page math site-wide, or (as here, on minima) inserts a configured MathJax script into a site-local copy of the theme’s head:

add_mathjax("yihui-minima")
build_site("yihui-minima")

A 2007 post on structural equation modeling: as migrated, the inline $\Sigma$ and the display formula are raw text; after add_mathjax(), both render

Julia Silge to Chirpy

A data-science screencast blog on the old Hugo Academic theme – heavy on code, plots and embedded videos:

migrate_hugo("juliasilge.com", "julia-chirpy", theme = "chirpy",
             only_referenced = TRUE, rerender = FALSE)
#> v 164 posts migrated

Academic’s [[menu.header]] (instead of Hugo’s standard menu.main) is understood, 123 posts arrive pre-rendered thanks to rerender = FALSE, and 81 {{% youtube %}} shortcodes – the percent-delimited form, with quoted arguments – become embedded players:

juliasilge.com before (Academic, left) and after (Chirpy, right). Academic stores the profile picture as author data (content/authors/), which has no automatic mapping – Chirpy’s avatar slot stays empty until you set avatar: in the config, one of the items the report leaves for hand-porting.

A typical screencast post. One reading note: the “before” comes from the Internet Archive, which does not archive YouTube iframes – the blank block on the left is where the original page showed the video. On the migrated site (right) the converted embed renders the same video again:

A screencast post before (Wayback Machine; the embed area is blank because the Archive does not capture YouTube iframes) and after, with the embed restored

Blogdown’s rendered posts wrap figure paths in {{< blogdown/postref >}} tags; those are resolved away during migration, so images point at the copied assets.

Full disclosure, and a practical note: 41 posts had no committed rendered output, so rerender = FALSE left their .Rmd sources in _source/ for re-knitting. Re-executing years-old code was not realistic for this demonstration, so those 41 files were removed before the build – on a real migration you would knit the ones you care about and drop the rest.

Jenny Bryan to Minimal Mistakes

A minimalist personal site on hugo-theme-sam, which keeps its menu in [[params.mainMenu]] with link/text keys – nowhere near Hugo’s menu convention. The fallback finds it:

migrate_hugo("jennybryan.org", "jenny-mm", theme = "minimal-mistakes",
             only_referenced = TRUE, rerender = FALSE)

The four menu pages become _pages/ entries wired into _data/navigation.yml, and the GitHub/Scholar profiles found in the content move into Minimal Mistakes’ author sidebar:

jennybryan.org before (sam, left) and after (Minimal Mistakes, right)

The about page, with the theme’s masthead navigation

Allan Quadros to al-folio

The migration this package was born for – an academic site with a hand-written publications page:

migrate_hugo("my_webpage", "my-new-site", theme = "al-folio",
             only_referenced = TRUE, publications = "bib",
             theme_color = "red")

allanvc.github.io before (Hugo, left) and after (al-folio, right)

publications = "bib" is the deterministic showpiece: the DOIs on the hand-written page are extracted, each reference is fetched as authoritative BibTeX from doi.org, journal covers are paired with their entries, and al-folio’s jekyll-scholar renders the result – filter box, DOI/Bib buttons and highlighted author name included:

The publications page: hand-written HTML vs. jekyll-scholar from DOIs

Beyond the migration: make it yours

A migration lands on the theme’s defaults. The customization layers (see vignette("jekylldown"), section 5) take it from “migrated” to “mine” without hand-written CSS – everything below is package functions plus, where noted, one config line. Left: as migrated. Right: after the recipe.

Julia Silge / Chirpy – the theme’s CSS variables, plus the one manual item the report left us. Academic kept her portrait as author data, so we copy it in and point Chirpy’s avatar: at it:

set_theme_style(
  accent = "#8e24aa",   # a nod to Academic's purple
  sidebar_background = c(light = "#f6eef8", dark = "#1d1428"),
  dir = "julia-chirpy")
# the avatar: copy the image, set one config key
file.copy("juliasilge.com/content/about/sidebar/avatar.jpg",
          "julia-chirpy/assets/img/avatar.jpg")
# in _config.yml:  avatar: /assets/img/avatar.jpg

As migrated (left) and restyled (right): accent and sidebar tint via set_theme_style(), and the portrait back in its slot

Jenny Bryan / Minimal Mistakes – no CSS variables here; the theme restyles through compiled skins, plus a Google Font inlined by set_theme_font():

set_theme_skin("dark", dir = "jenny-mm")
set_theme_font("Fira Sans", dir = "jenny-mm")

As migrated (left) and with the dark skin and Fira Sans (right)

Allan Quadros / al-folio – fonts, a warmer background per color scheme, and a free-form touch in a managed block:

set_theme_font("Lora", size = "17px", dir = "allan-alfolio")
set_theme_style(
  background = c(light = "#fffdf7", dark = "#1c1c1d"),
  dir = "allan-alfolio")
add_css(".profile img { border-radius: 50%; }",
        id = "round-avatar", dir = "allan-alfolio")

As migrated (left) and after fonts, background and the rounded portrait (right)

Every one of these blocks is idempotent – re-run with other values to change your mind, or remove it (e.g. add_css(character(0), id = "round-avatar", dir = site)). On minima the same set_theme_font(), add_css() and add_mathjax() (shown in Yihui Xie’s section) work unchanged; only the variable layer is theme-specific.

mirror server hosted at Truenetwork, Russian Federation.