Making a website with blogdown & Academic Theme for Hugo 1: setup to basic customization
join us on the glorious webtubeways of the blagoblag!
This is the first post in a series on building a website with R, blogdown, and the Academic Theme for Hugo. The next post will cover quality-of-life tweaks, and more advanced customization.
Update: Jan 3, 2021:
The main reason I thought this post was worth writing was that Alison Hill’s last published guide preceded major updates to the Academic theme for Hugo. But she has a new post on setting up your website using blogdown and Academic Theme for Hugo, i.e. the topic of this post.
You should use hers as your primary guide — there is like 90% overlap and she’s the expert — and maybe check here if you need a beginner’s perspective on particular topics.
Intro:
This is less a guide I wrote and more a mixture of guides/info from different sources (mostly by Alison Hill and Yihui Xie) annotated with my observations as a first-time user. If you want a more streamlined guide, Alison Hill’s 2019 slides on starting a website with blogdown and Hugo are the bees' knees, though not specific to the Academic Theme.
A few reasons you might want to use these guides anyways: it’s the most recent as of this writing 😎, I’ll detail some tricks / workarounds / failures, and I borrow
Who is this meant for?
Essentially, this guide is meant for people like me a week ago: I use R, rmarkdown, and GitHub daily, but I had roughly, oh, about exactly zero experience with HTML, Hugo, or the blogdown package.
I decided to write this in large part to document what I did so that I can work on my website in the future, particularly because blogdown + Hugo can be finicky. Hopefully these posts can save you some pain and frustration if you are also a first-time user.
Caveats
I am not an expert on any of this! I just started using these tools and, basically, if it worked, I moved on. So some of the suggestions here are likely sub-optimal. I tried to do my research, but please feel free to let me know if you have better ways to do any of this!
Preliminaries:
Note on changes to Academic Theme
As mentioned earlier, Academic Theme for Hugo had a big update last year: it became part of something called Wowchemy, and this appears to have broken things for some people, or required different settings, because
- its folder structure changed, and
- how it, um, handles some stuff is like, different. (I really have no idea 🤷)
On my first attempt building this site, I followed an older guide; the discrepancy in folder structure was confusing, and I ended up messing around with the actual theme files 😟. Then plotting broke 😳. Then the site didn’t deploy … and I ended up starting over 😖.
So follow a recent guide.
Resources
(ordered from most used to least used)
-
- These are for a different theme, but she literally wrote the book (along with Yihui Xie) on blogdown, and it’s easy to follow steps in this presentation format. Her slides are also purty.
- Her website and website repo were also frequently useful to me when troubleshooting.
-
blogdown documentation by Yihui Xie
- Yihui Xie is basically the Gandalf of the Fellowship of R Users.
-
- It was a little difficult as a first-time user to find the info I needed here, but if/once I found it, it was helpful!
Starting up:
- This section is almost all from Alison Hill’s slides.
Install latest blogdown and Hugo:
if (!requireNamespace("devtools")) install.packages('devtools')
devtools::install_github('rstudio/blogdown')
blogdown::install_hugo()
- make a repo on GitHub.
- create a new Rproject and connect it to the repo.
- in Rstudio: File –> New Project –> Version Control –> Git
- if you don’t know how to do these things, follow the links in Alison’s slides.
`yourGitHubusername.github.io`
. So you can't use that for this step.
Initialize site with Academic Theme
library(blogdown)
new_site(theme="gcushen/hugo-academic",
sample=TRUE,
theme_example=TRUE,
empty_dirs = TRUE,
to_yaml = TRUE)
After that finishes, see if the site builds locally.
- Use the “Addins” dropdown (end of the 2nd row of Rstudio’s menu bar) to select “Serve site” or use
blogdown::serve_site()
.gitignore
Add the resources/
and public/
folders to your .gitignore
file so that it looks like this:
.Rproj.user
.Rhistory
.RData
.Ruserdata
public/
resources/
Check deployment
Don’t skip this step! It will help you detect problems as you move forward.
Two common options for hosting:
-
continuous deployment via Netlify (via GitHub): awesome. Auto-updates website when you push changes to your repo, and you can also preview/deploy branches to test changes you make to the website before putting them out into the world..
-
GitHub: simpler at first, but a few more steps required for deployment every time you update.
option 1: continuous deployment via Netlify (recommended)
Steps:
- Push everything to your GitHub repo (you already added
resources/
andpublic/
folders to your.gitignore
, right?).
- I love RStudio’s Git tab, but don’t use it for this unless you like clicking, and waiting, and clicking, and waiting, and….
staging many files in Rstudio’s Git tab
- Instead, in the RStudio terminal (the tab next to your console), type:
git add -A # stages everything
git commit -m "init" # commit with message "init"
git push
- While that’s going, set up an account at netlify.com.
- Click “New site from Git” –> “Github” –> “Only select repositories” –> select your website repo.
- If you end up switching repos for some reason, you can always give Netlify access to another repo.
- Your url will be something oddly delightful like
drowsy-koala-d7ce09.netlify.app
.- Change it: “Site settings” link –> “Change site name”.
- You can always change the site name, or set up hosting on a new domain.
Cool! Now whenever you push to your repo, netlify will build it and serve your website.
Use the branch deploy feature to preview changes (such as a new post)! All you have to do now is create a branch AND make a pull request, and netlify will let you preview it! More details + suggested workflow here.
option 2: Github deployment
Steps:
- Build the site: either use
blogdown::build_site()
or the “Build” tab (next to Environment, History, Connections) –> Build Website- This builds your website locally, in a new folder named
public
in your project root directory.
- This builds your website locally, in a new folder named
- Push the contents of the
public
folder (not the folder itself, just what’s inside) to a GitHub repo named<yourGitHubusername>.github.io
. For example, my repo would be namedakseong.github.io
, and that would also be the url of my website.
Done! Super easy, but unfortunately, whenever you want to update your website or add content, you will need to follow these same steps.
Folder structure: a short tour
Alison Hill gives you a short assignment to figure out your folder structure, and I found it helpful to go through. Your folders / files are going to look a little different, though (updates since 2019, different theme).
Your folder structure will look like this (unless it has changed yet again!):
├───archetypes
├───assets # CSS, icons
├───config
│ └───_default # site customization
├───content
│ ├───authors # modify about page info in the 'admin' folder
│ ├───courses
│ ├───home # home page
│ ├───post
│ ├───project
│ ├───publication
│ ├───slides
│ └───talk
├───data
│ ├───fonts
│ ├───themes # "themes" = color scheme
├───layouts # overrides theme templates
├───R
├───resources # intermediary build files - delete often
├───static # place for files that do not need to get "built" by Hugo
│ ├───admin
│ └───media # images used with posts/projects
└───themes # NO TOUCH!
The comments above should be fairly self-explanatory, but the content
folder is worth discussing further.
The general idea is that the folders inside the content
folder either
- are a separate page in the website
- these folders contain an
index.md
file + widget.md
files
- these folders contain an
- or contain info used by widgets
- these folders usually contain a subfolder for each piece of content, e.g. each post or project
This is a little loose (e.g. the contents/home/gallery
folder doesn’t fit so neatly in here) but I find it useful to think of it this way.
New page folders
The content/home
folder is the only “separate page”-type folder here right now — the Academic Theme by default generates a 1-page website. Inside content/home
, you’ll see a file index.md
; open it up. It should say:
---
# Homepage
type: widget_page
# Homepage is headless, other widget pages are not.
headless: true
---
type: widget page
indicates that the page initialized by thisindex.md
file (the home page) is composed of widgets.- The other
.md
files inside this folder (content/home/
) are the different widgets on the home page: an “about” widget, an “accomplishments” widget, etc. - You can add new folders like this to create new pages in your website, but you have to mimic this structure. More on this in a later post.
Widget info folders
Folders containing info used by widgets will contain a file _index.md
— note the underscore — and typically subfolders for entries.
For example, the folder content/post/
is where your blog posts go by default, and each post gets its own subfolder inside content/post/
. The widget that uses the content in content/post/
is actually contents/home/posts.md
(a widget on the home page) which contains the lines
widget: pages
...<other options>...
page_type: post
widget:pages
indicate that this is a “pages” widgetpage_type: post
indicates that this widget draws its content from the foldercontent/post/
. (Scroll down to the “Recent Posts” section on the homepage, and compare the posts to the folders insidecontent/post/
.)
Basic customization
Now to make your website yours!
Use LiveReload
If it’s not already running, use blogdown::serve_site()
to serve/host your website locally, i.e. see your website in RStudio’s viewer pane. You can also open the site in a browser tab using the “show in new window” icon in the viewer pane menu bar.
-
This is LiveReload — an awesome feature! The site refreshes on save, so you can see how your changes affect the website…. or if they broke something, which is unfortunately always a concern here.
-
If changes you make do not seem to be appearing, stop and restart the local server by running
blogdown::stop_server()
, thenblogdown::serve_site()
.- You might encounter an error message about not being able to stop the server when you run
blogdown::stop_server()
, but just executing it again always stops the server for me — so far at least 🤞
- You might encounter an error message about not being able to stop the server when you run
-
If your site blows up over nothing like a low-blood-sugar toddler, try stopping the local server, deleting the
resources/
andpublic/
folders in your project’s root directory, and then starting the local server again.
resources/
contains intermediary build files, and will be auto-generated as needed.public/
is generated when you build the website using the “Build” tab.
Site config
There are 3 main files you’ll want to edit:
config.yaml
: general site configuration (next section).config/_default/params.toml
: personal info + site feature configuration, e.g. syntax highlighting.config/_default/menus.toml
: navbar configuration.
With LiveReload, you shouldn’t have too much trouble figuring out params.toml
(heavily commented) and menus.toml
(fairly straightforward) — and if in doubt about a particular setting in params.toml
or menus.toml
, leave it for now.
config.yaml
requires a bit more care, however.
config.yaml
In your root directory, change the following fields in config.yaml
:
title:
site name (your name if this is a personal website)baseurl:
set it to the url (in quotes) your site has been deployed to.- you didn’t skip that step, did you? If you did, you can also change it to ‘/’. For now. But it must be specified.
- include “https://” in the url. Also, see Yihui Xie’s post on redirecting HTTP to HTTPS
ignoreFiles:
add the following to the default list underignoreFiles
- \.knit\.md$
- \.utf8\.md$
I have seen some guides recommend including "_files$"
in ignoreFiles
, but this will break plotting in code chunks in .Rmd-generated posts.
Almost done. Add the lines:
relativeURLs: yes
canonifyURLs: yes
relativeURLs: yes
is necessary for cloud setup.cannonifyURLs: yes
: consolidates duplicate URLs.
Last, beneath permalinks
, I suggest adding post: /:year-:month-:day/:slug/
(follow indents; this modifies post urls, e.g. “…/2020-12-29/making-of-1/” rather than “…/post/making-of-1/").
Your info
For ease of editing, bring the about.md
widget to the top of the page (deactivate the hero.md
and demo.md
widgets in content/home/
by changing set active: false
, or make these widgets come after the about.md
widget by setting weight:
> 20). It will just be easier to see (using blogdown::serve_site()
) the changes you’re making. You can always reactivate/reorder these widgets later.
The about.md
widget in content/home/
uses info from the folder content/authors/admin/
.
- For the text, edit
_index.md
with your info. Quick note: thebio:
field in the header is what appears next to your name at the end of posts, not in the section generated by the “about” widget. - Add your picture by placing a .jpg image into
content/authors/admin/
and naming itavatar.jpg
Other widgets
Poke around content/home/
and modify the content of the different widgets with your info.
- deactivate the widgets you don’t want by setting
active: false
. In general I would not delete these, as they are useful templates. - modify the order in which widgets appear using the
weight:
parameter (lower numbers = higher on page)