How to create a simple academic website
Some of the most popular resources I’ve previously shared, like this screencast, have been about how to create an academic website. It’s important for academics at any career stage to have a site that they fully control. Most institutions offer their staff personal webpages, but these typically have little flexibility and are lost when people leave institutions.
I’ve been playing around with the Quarto publishing system over the past few months, which also includes the capability to build websites. I’ve been impressed at how Quarto can build academic papers (I wrote this preprint using Quarto), so I wanted to try my hand at using it to rewrite my own website, which is where you’re reading this very post. Compared to how I built websites in R in the past, which was pretty hacky to be honest, using Quarto was a much smoother process. I also wanted a way to easily update my publication list, based on my Zotero library, and to add links to materials associated with papers, along with open access versions of paywalled papers.
In this post I’m going to walk through two different ways you can make a site like this. First I’ll walk through how to clone the whole thing from GitHub, which requires you to edit in your own info. Second, I’m going to show you how to make a site like this by using a Shiny web app I made that creates the required code with your own info from the get go.
What you need
Quarto and R. The site itself relies on a single R package — knitr — so there’s no long list of dependencies to work through.
One thing worth pointing out first, because the commands below switch between the two: RStudio’s Console and Terminal are two tabs in the same pane. The Console runs R code, while the Terminal runs your computer’s own command line. Anything like install.packages() goes in the Console; stuff like git, quarto and brew commands go in the Terminal.
You may already have Quarto as recent versions of RStudio ship with it bundled. You can double-check from the Terminal in RStudio:
quarto --versionIf that comes back with a version number, you’re good to go. If it says command not found, install it from quarto.org, which has installers for macOS, Windows and Linux. On a Mac with Homebrew you can instead run in Terminal:
brew install --cask quartoOnce it’s installed, add knitr from the R console:
install.packages("knitr")Getting it running
Now run this in the Terminal.
git clone https://github.com/dsquintana/dsquintana.com.git
cd dsquintana.com
quarto previewThat serves the site locally with live reload. Here’s what you need to do to make it your own: replace publications.bib with your own1, swap the profile photo with your own photo, and work through index.qmd, _quarto.yml, and whichever pages you want to keep. Either edit pages or delete them.
Those two filenames are each hardcoded in exactly one place, so the easiest route is to name your files publications.bib and profile.jpg. A PNG is fine too, but then you need to change the image: line at the top of index.qmd to match — if the name and the file disagree, Quarto renders a missing image without raising an error.
You’ll also want to empty links.csv down to its header row. Mine holds a hundred-odd links to my own data and code, each keyed to a citation key from my bibliography — against your library they’d match nothing, and every row would show up as a warning when you render. Deleting the file entirely works too; the site renders fine without it. You’ll just be missing any additional links to data and code. The README.md has the full list of what you need to do.
Or skip the cloning
Starting from my own webpage means deleting a lot of it first, and assumes you’re reasonably comfortable in RStudio. So, I also built a website builder. With this app, you fill in your name, a bio, and a few links, upload a photo and your Zotero BibTeX export (see above), and it hands back a zip of the same site with your details already in it and mine gone. This generates a two-page version that includes a homepage and a publications list.
You’ll still need R and Quarto installed to build what it gives you (see above).
The publication list
Quarto handles citations through pandoc’s citeproc, which is nice, but it creates one flat bibliography per document. I wanted mine grouped under year headings, newest first.
There’s no built-in way to do that, so bibtools.R takes a fairly blunt approach by splitting the .bib file by year, running each year’s subset through pandoc separately, and pasting the resulting HTML fragments back together under ### headings. The whole publications page is then three lines:
```{r}
#| echo: false
#| output: asis
render_by_year("publications.bib", csl = "apa.csl")
```Add a paper in Zotero, re-export, re-render. New years appear on their own.
Attaching data and code links
For me, it was important to add links to data and code associated with papers. BibTeX can’t help here, since there’s no standard field for it, so I put together a solution whereby the links live in a separate file, links.csv, joined to papers by citation key:
citekey,label,url
Quintana2023,Data & code,https://osf.io/dr64q/
Quintana2023,Web app,https://dsquintana.shinyapps.io/metameta_app/
bibtools.R reads that file and injects a small labelled link into each matching reference. One row per link; a paper can have as many as you like (e.g., data, code, preprint). The labels are free text, so you decide what categories you want — mine are Data & code, Code, Preregistration, Preprint, Web app, and Open access article.
As links.csv is kept separate from the .bib, Zotero remains the ground truth for bibliographic data, and re-exporting never messes with these links.
Putting it online
The normal pattern for a static site, like this one, is to connect a host to your repository and let it build on every push. That doesn’t work here, because the publication list is generated by R at render time, and neither Netlify’s nor GitHub Pages’ build image ships with R. Installing R and knitr on every deploy is possible, but it’s slow and one more thing to break. So I build locally and commit the output.
Committing build output is normally poor practice, and it does make the commit history noisier. The tradeoff is worth it here, I think, because deploys can’t fail from a dependency problem, as nothing is being built on the server. The one downside is that quarto render becomes mandatory before pushing — skip it and you deploy your previous build, silently and with no error.
Getting it onto GitHub
If you used the builder app, the folder it gave you isn’t a git repository yet. From the Terminal, inside that folder:
git init
git branch -M main
git add -A
git commit -m "Initial commit"If you cloned my repo instead, you already have a repository — but it still points at mine, so you’ll want to repoint it in a moment.
Now make an empty repository at github.com/new (assuming you’re logged in to your GitHub account). Leave “Add a README”, “.gitignore” and “license” all unticked as you already have those. Then, swapping in your own username and own repository name:
git remote add origin https://github.com/YOU/YOUR-REPO.git
git push -u origin mainIf you cloned my site, use git remote set-url origin ... instead of git remote add.
One thing that sometimes catches people out: when git asks for a password, your GitHub account password won’t work. You need either a personal access token pasted in place of the password, or the GitHub CLI (gh auth login), which sets this up for you.
Connecting Netlify
In Netlify: Add new site → Import an existing project → GitHub, then pick your repository. Two settings matter:
- Build command — leave it completely empty
- Publish directory —
_site
That’s the whole configuration. Netlify serves the folder you already built.
A free address, or your own domain
Netlify gives every site a free address like something.netlify.app, and you can change the something part in the site settings. That’s a good place to start, and nothing about your setup has to change if you add a domain later.
If you do want your own, buy one (they’re usually around $10–15 a year), add it under Domain management, and follow Netlify’s DNS instructions.
Whichever you use, turn on Force HTTPS in Netlify’s domain settings once the certificate has been issued. Without it your site is still reachable over plain http://, and browsers increasingly make that look alarming.
Updating it from then on
Once that’s set up, publishing a change is three commands:
quarto render
git add -A && git commit -m "Update site"
git pushNetlify picks up the push and redeploys in about a minute. The first line is the one to remember: Netlify serves whatever is in _site/, so skipping the render pushes your previous build and nothing will tell you that’s what happened.
Reuse
The code is MIT licensed and the content is CC BY 4.0, so take whatever’s useful. You don’t need to credit me for the code, though I’d be glad to hear about it on LinkedIn or Bluesky if you build something with it.
Footnotes
To do this, in Zotero create a collection that only contains your publications, select all of them, right-click, then select ‘Export items’ (choose BibTeX as the format)↩︎