Featured image of post Migrating Serendipity (s9y) to Hugo

Migrating Serendipity (s9y) to Hugo

Moving an old serendipity blog over to a modern static web site generated by Hugo.

My Serendipity blog was woefully outdated and getting it upgraded would have been a lot of work. Instead, my friends Elie and Celine convinced me to switch to a more modern system. We settled on Hugo which generates completely static web sites. The result was a fast and essentially serverless website.

The whole setup required the following steps:

  • Import RSS feed and convert it to markdown
  • Fork Jimmy Hugo theme stack on Github
  • Commit the generated markdown and images
  • Configure a Firebase static web site
  • Configure Cloudflare to proxy Firebase
  • Set up Github Actions to generate the page and push it on each commit
  • Create a docker container with Hugo and the git repo

A simple Jupyter notebook from Elie converted the RSS feed into markdown.

Fetching Posts

1
2
3
4
5
r  = requests.get("https://www.<yoursite>.org/rss.php?all=1&version=2.0")
raw_feed = r.content
feed = feedparser.parse(raw_feed, sanitize_html=False)
posts = feed.entries
print("total posts", len(posts))

Setting up directories

1
2
3
4
workdir = Path("../../<yoursite>.github.io/content/post")
imgdir = Path('../../<yoursite>.github.io/static/images')
workdir.mkdir(parents=True)
imgdir.mkdir(parents=True)

Writing Markdown

You may need to adjust this to your own needs but it gives you a sense of the mechanics.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
for p in tqdm(posts, desc="creating posts"):
    title = p.title
    slug = p.title.lower().replace(' ', '-').replace('--', '-')
    slug = re.sub('[^a-z0-9-]', '', slug)
    postpath = workdir / f"{slug}" / "index.md" 
    
    date = p.published
    if 'tags' in p:
        tags = [t['term'] for t in p.tags]
    else:
        tags = []
    content = p.summary

    # dl images and get info
    img_info = get_images(content, imgdir)

    # markdown
    md = markdownify(content).replace('\n\n', '\n')   

    # replace with relative images
    for i in img_info:
        md = md.replace(i['url'], f"/static/images/{i['fname']}")

    with codecs.open(postpath, 'w+', encoding='utf-8') as o:
        o.write('---\n')
        o.write(f'layout: post\n')
        o.write(f'title: {title}\n')
        o.write(f'slug: {slug}\n')
        o.write(f'permalink: posts/{slug}\n')
        o.write("author: <yourname>\n")
        o.write(f'date: {date}\n')     
        o.write(f'tags: {",".join(tags)}\n')        
        o.write('---\n')
        o.write(md)

Setting up the Git Repo and Actions

Use git to clone the Jimmy hugo theme stack starter. This also sets up a basic Github Action for you. This action will need to changed so that instead of publishing to Github pages, it will deploy to Firebase.

Replace

1
2
3
4
5
6
7
- name: Deploy to GH Pages 🚀
    uses: JamesIves/[email protected]
    with:
        branch: gh-pages
        folder: public
        clean: true
        single-commit: true

with

1
2
3
4
5
6
7
- name: Deploy to Firebase
    uses: FirebaseExtended/action-hosting-deploy@v0
    with:
    repoToken: '${{ secrets.GITHUB_TOKEN }}'
    firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_PROVOSBLOG }}'
    channelId: live
    projectId: <firebaseprojectid>

For all of this to work, you need to follow the Firebase instructions on how to configure the right secrets in Github. To help with serving and staying below the Firebase quota, you can also set up Cloudflare to proxy and cache the traffic. It’s incredibly powerful.

Making the development mobile

Writing in markdown and manually inserting images into a blog post can be a little bit tedious. To make the whole setup easier and more portable, I created a docker image with Hugo and the git repo that contains the blog. Once the image is ready, you can carry it around with you. At the moment, I am writing this blog post on a Chromebook with VSCode attached to the container. You can run your container with:

1
2
3
4
5
6
7
$ docker run -it -p 1313:1313 1cef71c9fd7a /bin/bash
$ cd server/<yousite>.github.io/
$ hugo server --bind=0.0.0.0
Change detected, rebuilding site.
2022-12-18 23:51:51.511 +0000
Source changed WRITE "/server/<yoursite>.github.io/content/post/migrating-to-hugo/index.md"
Total in 211 ms

Afterwards, you can point your local browser to `http://127.0.0.1:1313/ and see Hugo update and reload the blog as you write it.

Publishing A New Post

This only requires writing the blog post and then commiting and pushing it to github. This all takes place just inside of VSCode. The configured Github Action will take care of the rest.

The views expressed on these pages are my own and do not represent the views of anyone else.
Built with Hugo - Theme Stack designed by Jimmy