Thoughts on Building a Quarto Website
I’ve been using Quarto to blog for about seven months now, and I’d like to write a quick summary of my experiences and give a few tips and tricks on how to use it to publish a website or blog. This post will come from the R/ RStudio perspective, which has tight Quarto integration. Python folks, you too can have a quarto blog and website, but I have yet to find a good tutorial to link you to.
I followed a couple of great tutorials, and I won’t duplicate that material here. I recommend you follow the tutorials by Sam Csik (website set-up and blog set-up) and Andrew Rapp (and I’ll get more specific about which parts in a minute), but I recommend reading this blog first. Some of this stuff won’t make sense until you do it, but it will help you follow the tutorials better. You can follow the tutorials without knowing any of this (I did), but I did run into some problems with the GitHub part of things, which are memorialized in my sad first post. I have found a workaround to that, which I discuss in the GitHub/Versioning section of this post.
I like Quarto websites because they let you have a decent looking website with minimal effort to set it up. The content is the most important part of your website/ porfolio.
Overview of Quarto and Websites
From the Quarto website, Quarto is:
An open-source scientific and technical publishing system
Author using Jupyter notebooks or with plain text markdown in your favorite editor.
Create dynamic content with Python, R, Julia, and Observable.
Your Quarto Files Are Real Coding Projects
If you’ve used any method of mixing code and text blocks, Quarto’s style will feel familiar to you. I want to emphasize this part a bit more in case you haven’t used markdown or Jupyter Notebooks. If you download any of my Quarto documents with code blocks you can open it and run the code. (You may need to change file paths or install the libraries I used). All my datasets are included in the repo for the website. This isn’t just blog of me going blah, blah, blah (this post aside)- the majority of my blog posts are complete projects with fully executable code.
Creating a Website Project in RStudio
As an R user, I chose to implement my website through RStudio. Quarto is a project supported by Posit (the company that makes RStudio), so the integration is seamless. You can create a project in RStudio and designate it as a Quarto website, and it will set things up for you. You manage it like any other project. There are numerous tutorials for how to set up the website in RStudio. The official documentation for this process is here. There is less information about how to set it up for Python folks.
In RStudio, choosing the website project will create some basic files you need- a YAML file and an index.qmd file. The YAML file gives information about what the output of rendering a quarto file (*.qmd) should be. In this case, it is set to produce HTML, but Quarto is a scientific publishing system, so your YAML could tell it to render a PDF or a PowerPoint or any number of outputs.
The Difference between Executing Code and Rendering the Document
Code written in a Quarto document (a *.qmd file) can be executed as normal in the RStudio environment. The variables you create show up in the environment pane. You can view them and interact with them in the console as usual. You execute the code using the run button at the top of the screen or cell block by cell block with the run button included in each code block. At this point, things behave like standard code.
There is an additional button at the top of the file that says render. Pushing this button executes the code and the instructions in the YAML headers to create the type of document you want. In this case, it generates the HTML files and copies related assets (jpg, etc.) to the doc folder in the project. These are the files that are used to generate the webpage.
Note that rendering the file does not create any variables that you can access in the environment or console. So, usually, you want to execute the code as you are working on it, not render it. When you render, the finalized webpage will pop up in your web browser. (Sometimes it doesn’t, and I’m not sure why, but you can find the HTML file in the docs folder and open it directly.) You do want to render the page at least once in draft mode to make sure all the formatting looks good before you publish it for real. I try to make sure my tables and code blocks don’t have horizontal scroll bars, so that is something I check for. Then, I’d reformat the line breaks in the code or the table to narrow it.
There is also a render website button in the build tab in the pane that contains the Environment, History, Connections, and Git windows. This re-renders every page on your website (but may or may not re-execute code depending on the “freeze” setting in the YAML header or file). The best practice is to re-render the website whenever you change anything. This got very slow, very quickly, as I started to generate more content. In practice, you can probably just render the relevant pages. If you change the navigation bar or something else that applies to all pages, then you certainly need to re-render everything.
Why is Everything Named index.qmd?
If you go to a URL that doesn’t have a specific page listed (just paths/folders), the browser will automatically serve you the index file. So https://lsinks.github.io/index.html and https://lsinks.github.io/ give you the same page (the index.html file found in the root directory of the website). Many tutorials recommend that you name all your blog posts index.qmd as well. Using index.html makes the URLs shorter. The downside is you end up with a million index.qmd files in your project. I tend to reuse sections of code, so I frequently had multiple index files open in the editor, and it was confusing to navigate between them. I switched to giving each blog qmd file a short and unique name. This practice means your URL needs to be the full path + file name (e.g., https://lsinks.github.io/posts/2023-09-08-web-scraping-tombstone/web-scraping.html) whenever you use it.
Getting the Basic Website Up- Specific Hints for Following the Sam Csik Tutorials
Start with the tutorial on setting up your website. The tutorial assumes you have Git set up, have a GitHub account, and know how to get your credentials so you can push stuff from your local machine to the GitHub website. If you don’t, I suggest looking at the resource Happy Git and GitHub for the UseR, specifically the Installation section, which starts in Chapter 4.
GitHub and Versioning in RStudio
My website is published on GitHub pages. The web pages only appear once I push them to GitHub and GitHub publishes them. RStudio has built-in Git/GitHub integration that should make it super easy to do versioning. (Not just for a webpage, but in general.) I have had horrible luck with this feature. I frequently get versioning conflicts that are very difficult to resolve. Searching the error messages indicates that the error is related to someone else editing the files, which isn’t the case at all.
I first ran into this issue when setting up the website. I got to the “Publish your site with GitHub Pages” in Sam Csik’s tutorial, and you stage, commit, and push your changes to the GitHub repo. I ended up in cycles of cryptic error messages about unresolvable conflicts that I couldn’t figure out how to resolve other than by deleting the entire repository and starting over. (No great loss since there wasn’t any content at that point.) At the time, I thought it was something specific to the website project, but since then, I have run into this issue with regular projects and repos, too. Anything where I try to handle versioning within RStudio has a high chance of going catastrophically wrong.
So, I always handle versioning outside of RStudio, and as an extra layer of paranoia, I only pull or push changes when RStudio is closed. GitHub Desktop has a nice user interface if you aren’t comfortable with a terminal window. Happy Git and GitHub for the UseR recommends a different client, GitKracken, but I haven’t used it.
This might very well be a me problem; I certainly didn’t have much luck finding others with this issue when I googled. If you’ve been using the Git tab in RStudio and have had non-fast-forward errors before (without an apparent reason), then maybe you want to do what I’ve done and not use the RStudio Git interface.
Adding the Blog
Adding a blog to your webpage is covered by another Sam Csik tutorial. This tutorial is straightforward if you’ve completed the first tutorial.
A blog’s index page (the listing page) automatically updates all the entries when you generate them and styles the listing in specific ways common to blogs. My website has two blogs- the actual blog that you would recognize as a blog (and the section under which this post appears) and my portfolio page. I wanted my past work to have nice thumbnail pictures, so I just set it up as a blog and had Quarto style it automatically. Keep this trick in mind as you are building out your page. A stealth blog can add a very sophisticated look to a page. And since the listing page is created dynamically, you don’t have to update it if you need to add additional content.
Names and Middle Names in the YAML header
The only issue I ran into, and which took me a ridiculously long time to sort out, is that she used the author and citation tag in the YAML header to automatically create a “For attribution, please cite this work as: {citation}” at the bottom of every blog post.
I dutifully entered “name: Louise E. Sinks” in the header and have been generating incorrectly formatted citations for months:
E. Sinks, Louise. 2023. “Creating a Blog.” March 14, 2023. https://lsinks.github.io/2023-03-14_tester-post.
The solution, which is not so easy to find in the Quarto documentation, is to use:
- name:
given: Louise E.
family: Sinks
The citation then handles the middle name/initial properly and not as part of the last name. (This issue may or may not be fixed on earlier posts when you read this, since I will have to go back and fix every post.)
Of course, you may not want to have a citation for your webpage, so you can always omit that section.
Adding Additional Pages is Easy
The steps you used to add the blog page can be extended to other pages. Both additional static pages and listing pages for the blog can be added to the quarto YAML file. You can see mine here. In fact, you can view the entire structure of my website on Git Hub. Feel free to look at the *.qmd files and the _quarto.yml file to see how the website is structured.
Give GitHub Pages Time!
Sometimes, the changes take a while to show up live on the internet. This may give you the impression that what you did isn’t working. I know I changed a bunch of things initially and got very frustrated because I didn’t see what I expected on the live website. GitHub will email you if your deployment fails. Until you get that message, assume that the changes are just slowly propagating across the internet. Don’t panic and change things randomly like I did.
Decide on a Convention for Categories
Decide how you are going to name your categories. If you look at mine, they are a mix of upper and lower case. You should probably pick one from the start, so you don’t end up with multiple versions of the same category. Also think of what types of things you’ll include. If I use and explain a particular package heavily, I include the package in my category list. If I just use the package, then I don’t. Having some rules from the start will make things a bit easier in the long run, but don’t get too caught up in designing the perfect categorization system.
Adding More Features
These are all strictly optional, but might be nice to have.
Features Suggested by Albert Rapp
Albert Rapp’s “The ultimate guide to starting a Quarto blog” is an invaluable resource for adding advanced functionality to your blog/website. You can skip all this stuff for now or forever, too. The sections I did implement were:
adding social cards (called Twitter cards in the tutorial), which is when a thumbnail and the headline are shown when you share a link (or no headline if you are posting on X).
adding a comments section
adding Google Analytics and a cookies notice
adding renv, which I did completely wrong. I’ve been using renv, but you do need to follow his detailed instructions on linking a specific snapshot to one particular blog post.
He also has sections on customizing the styling with CSS and also creating series (which is another example of using the blog feature to create customized pages). He publishes his blog through Netlify rather than GitHub pages.
Alt Text
Alt text lets you add a written description to pictures and figures. Alt text makes your content more accessible to visually impaired visitors. I recently became aware that Quarto has support for this feature and have implemented it going forward. (All my portfolio projects have alt text, but my blog posts before this one don’t.)
Steal Some Code!
If you see something cool on a Quarto/ GitHub pages website and you can’t figure out how to do it, go look at the source code in their repo. Do you like the embedded video in my blog post on web scraping? Go look at that folder at GitHub. See where I stored the asset (*.mp4) and how I called it in the qmd file. Then, implement that yourself. (Here’s the official documentation for embedding video if you prefer.)
Obviously, I’m not advocating that you plagiarize anyone’s website! But taking code snippets and adapting them to your needs is fine. And it is nice to give a link or a shoutout to the source you found helpful.
Tips for Improved Workflow
This section isn’t relevant to setting up the website but might be helpful to keep in mind as you start producing content. Everyone’s workflow is different, so there is also a huge dose of “your mileage will vary.”
Spell Checking
Spelling and grammar checking, or lack of, is one of the most significant weaknesses of the process. RStudio does have a built-in spell checker, but it could be better. Sometimes, I live dangerously and just use that and post. But I do like a more thorough editing process.
I’m not the only one with this complaint. There are several proposed solutions out there (grammar checker R package, another package, and writing a ChatGPT shiny app to spell check) but the ones I tried didn’t work well for me.
For most of my other writing, I use the Grammarly spelling and grammar checker. The Grammarly plugin works terribly inside RStudio, so I usually end up copying and pasting text into the online Grammarly site and then copying it back down to the qmd file. I don’t like this process. I end up with multiple copies of the code/text in various places. You must also be careful to prevent it from correcting the code blocks, which is probably true for most checkers.
I do try not do extensive formatting (styling code in text, adding lots of headers, figures/alt text, and links) until after I’ve used Grammarly. Pasting the text back into RStudio often screws up the markdown and Grammarly often wants to spell-check formatting codes and mess them up.
Clean Up Old Files
Draft posts and pages with the draft: true setting in the header will be rendered at HMTL in the docs folder but not published. This means if you end up renaming the page or deleting it, you need to clean out the rendered files in the doc folder as well as the qmd file. I run into this most frequently with blog posts. I often drafted them with a guess on the publication date (and my folder structure includes the date). If the date changes, the older version won’t be automatically deleted from docs, even if the file that it is rendered from is deleted and you re-render the website. If this doesn’t make sense now, don’t worry about it.
Draft Complicated Things in Another Project
Incomplete and error-ridden code will cause the rendering of your website to fail, even if the offending file is marked a draft. So, for more complicated code, draft it elsewhere and copy it into the website project when you are ready to go.
The huge caveat to this is that you really need to pay attention to your file paths and folder structures. Your tester project likely has a simplified structure compared to your website. (Your tester project might be completely flat, while its final location in your website project might be in a subfolder of your blog folder.)
Complicating this a bit is that in RStudio, the relative path starts in the project directory for code and in the local folder of the qmd file for rendering. The most straightforward approach is to use here to reference all your paths back to the same starting point (the root directory of the project.)
The Turtle Says Just Type
I was supported by the best Technical Turtle during this process. When I wrote my first post, I didn’t really have a good thumbnail, so I just included a picture of him. He does occasionally take a more active role in my coding, by crawling across the keyboard and generating a bunch of letters (as you see in the thumbnail). And to some extent, you should take that lesson to heart- just type something. Your first post(s) are going to be terrible. Look at mine. I couldn’t figure out how to make hyperlinks, so I just dumped them as text. I didn’t even grab the right URL for one of the tutorials (I used a link to a specific section rather than the tutorial as a whole). That post is mostly a rant about how I can’t figure out GitHub.
Lots of stuff isn’t perfect here, even now. But I post them anyway. And I promote them on social media as well. It is terrifying to publicize work that you know could be better, but you can never achieve perfection.
Quarto enables you to start publishing content quickly. Do not get bogged down in customizing your style sheets and tweaking all sorts of things. Use an off the shelf theme and just start coding.
Citation
@online{sinks2023,
author = {Sinks, Louise E.},
title = {Thoughts on {Building} a {Quarto} {Website}},
date = {2023-11-01},
url = {https://lsinks.github.io/posts/2023-11-01-website-building/website.html},
langid = {en}
}