How to easily make a website for free

Author

Luke

Published

July 28, 2024

Disclaimer (dated 2024-11-03)
  • While all the code in this post still works, I consider this post “outdated”.
  • I have learned a lot more about Quarto since writing this post, and would structure this guide differently today.
  • For example, I would reconsider the whole “hosting” section, as it’s not very beginner-friendly.
  • Check out my updated guide here


Since I am not much of a social media user (never have been), I have come to think about personal websites as a useful way to still have a presence on the internet, either as a way to share what I’m up to or as a sort of virtual business card. However, I am also neither a professional web developer nor willing to spend money to make something as simple as a ‘static’ webpage. Luckily, I did not have to and you should not have to either.

As it turns out, there are multiple frameworks you can use to quite easily make a website, using almost zero actual web development code (think: HTML, CSS, JavaScript), although knowing these certainly helps. Some of the popular open-source ones include Jekyll, and Hugo, but today I want to talk about Quarto, which is particularly useful if you use \(\LaTeX\) or want to show off some code/computations.

Quarto, which is an open-source project developed by Posit, the company behind the popular IDE called “RStudio” is actually much more than just a framework for creating websites. This project really was intended to unify a series of different R-markdown extensions people wrote over the years. This means you can use Quarto not just for websites, blogs, and code notebooks, but also data dashboards, books, presentations, and who knows what else.

If you’re not familiar with R-markdown, it’s essentially how people who code in R prefer to have code and text in one file (like a Jupyter notebook, if you know that). If you don’t know any R, don’t worry. Despite the historic links to R, Quarto is actually completely language and IDE agnostic. The only languages required for setting up a website with Quarto are Markdown, which can be learned by anyone with 5 minutes to spare, and YAML, which also can be learned as you go along.

If you want to use the code and files I will be sharing, some knowledge of Git (version control software) will be valuable. Bash (the language that terminals on Linux and Mac OS use) will also be helpful. If you don’t know anything about git and terminals don’t worry too much, as I’ll try to make it as approachable as possible here by showing you how I did it. If in doubt, I encourage you to search for the relevant information you need, or perhaps use the AI model of your trust. I personally think that Git is the hardest part about copying my set-up as it’s something people who don’t write a lot of code are unlikely to know very well. Luckily, the commands we will be using are quite basic, so it should not be too hard to find the information you need if you get stuck.

So let’s get started, shall we? We can use Quarto to render Quarto markdown (.qmd) files into HTML which will be hosted on a Github server, enabling us to have a publicly available website. The files have to be hosted on a server connected to the internet if you want other people to be able to see the website. If you want to host your code somewhere other than Github, my incoming blabbering about Git and Github might not be terribly relevant to you. Instead, you should probably check out this site once you’re ready to show off that shiny new site.

Installation and setup

First, you’ll need to install Quarto and Git. For Git, there must be endless tutorials, just search “How to install git on [your operating system]”. For Quarto I’d encourage you to just follow their guide on their website for this, as there really is nothing much I can add to this part of the process. Then, for actually setting up the website project, their guide is perfectly comprehensive. It’s only after this step where you would have to dig deeper in the documentation (which you should definitely be reading after giving my suggestions a shot) and experiment yourself to figure out how to achieve the website of your dreams, so hopefully this is where sharing my process will actually start to be helpful.

Key files and commands

Now with your project initialized. Let’s quickly highlight some of the important files and concepts. The most important file is the _quarto.yml file, which basically controls the high-level structure of the website and some of the global settings. I’ll assume you have figured out how to render and preview the files you currently have in place from the guide on how to create the project. As you should be able to see with the default files, each page is a .qmd file.

If you haven’t yet, just render the files to get a first feel for what the final product looks like. Rendering and then previewing should open your browser, with the site your files give rise to displayed. If not, you are probably overdue some bug hunting. Keep in mind that our preview showing in the browser does NOT mean that the website is public!

The _quarto.yml

Here’s what my .yml file looks like:


project:
  type: website
  output-dir: _site

website:
  favicon: "assets/favicons/favicon.ico" 
  page-footer: "Powered by <a href='https://quarto.org' target='_blank'>Quarto</a>"  
  open-graph: true
  site-url: "https://lukmayer.github.io"
  title: "<img src='assets/favicons/favicon.ico' alt='Logo' style='height:40px; vertical-align:middle;'>"
  navbar:
    left:
      - href: index.qmd
        text: "Home"
      - href: research.qmd
        text: "Research"
      - href: cv.qmd
        text: "CV"
      - href: blog_index.qmd
        text: "Blog"
      - href: about.qmd
        text: "About"
    right:
      - icon: rss
        href: blog_index.xml
      - icon: envelope
        href: mailto:willuk@vivaldi.net
        aria-label: E-Mail
  


format:
  html:
    theme:
      dark: [darkly, theme-dark.scss]
      light: [flatly, theme-light.scss]
    css: styles.css
    toc: true

extensions:
  - copy-button

Let’s go over what each section does. In the project header, one important thing to note is the output-dir. Here, I specify that I want Quarto to render the files we will host later into the directory called _site. This will be a sub-directory in your project folder and can have any name. The reason we are not rendering to the root project directory is that Github really does not like this, and may fail to host your site as a result.

In the website header, I have the field “favicon”. If you don’t yet know, a favicon is the little image that websites feature on your browser tab, most commonly their logo. In the field, I simply specify the relative directory (relative in the sense of within my project files) in which the image I would like to use sits. I made my favicon using favicon.io.

The “page-footer” field displays a message of your choice at the bottom of each page in your site. In this case, I embedded a link into the string with HTML. In case you don’t know HTML, its the stuff between .

The “href” field specifies the link, “target = ‘_blank’” will ensure that clicking the link opens a new tab, and finally, the text between > and < specifies the text that I want to embed this link in. If you’re confused by that have a look at the rendered version. The open-graph tag is for link previews, which some websites use. So if someone shares a link to your website on a site that allows link previews, it’ll show a nice pretty preview with a picture. You can configure exactly what the link preview will show, but I didn’t bother with this.

The “site-url” field specifies the domain your website will be on. I needed this for some links to work correctly on the finished page. It’s not necessary to have this before you have deployed your site I don’t think.

My “title” field uses HTML to link to my favicon and render it at a certain size, which I felt looked quite stylish. This can just be text if you prefer. The “navbar” field controls what my navigation menu looks like. In this case, I use a bar at the top of the website.

On the left side of the bar, I link to different pages (my markdown files) and control the text that will be displayed on these links. On the right, I use some icons and add links to things, such as my RSS feed (this is to follow my blog, don’t worry about this for now), as well as for authoring an email to me. There are tons of icons available that are built-in to Quarto, which you can find here.

In the “format” section, I basically specify the themes of my website, one dark theme and one light theme. The built-in themes can be found here. If you specify one dark and one light theme, Quarto will add a toggle for people to switch between them in the navbar. The order of the fields determines which one is active by default. So in my case, the page is dark by default. In the dark and light fields I also add some .scss files that basically just change the color of the navbar and the font. This can get a little more technical so don’t worry too much about it if you like one of the built-in themes.

Finally, in the “extensions” field I add the copy-button extension which allows people to copy the code from any code chunks I am embedding in one click. There are actually tons of cool extensions you can use, which are linked here.

Setting up a blog within the website

A blog is a nice place to share things in posts. In Quarto, that basically means having a list of pages on a blog index page. The pages listed on this index all sit inside a folder inside your project directory. In case you didn’t realize yet, every quarto markdown document has a so-called “YAML header” which is indicated by the three hyphens that denote the beginning and ending of this header. The header specifies fields and settings for that page alone. Here’s what the header looks like for my blog index.

---
title: "Blog"
listing:
  type: grid
  fields: [image, date, title, description, reading-time]
  contents: posts
  sort: "date desc"
  sort-ui: [title, date]
  filter-ui: [title, date]
  categories: true
  feed: true
---

So in my case, I give my blog_index.qmd a title, choose a layout for my blog (there are a couple of options here), some fields that will be shown in my blog such as how long it takes to read the post (again, there is a list of things you can easily put here). The contents field specifies the folder that features all the pages I want to be listed on blog_index.qmd.

The next couple fields add UI for sorting/filtering and the categories field allows you to add category tags to posts which can be nice. I’ll show you how to add categories to posts in a second. The feed field enables RSS feed generation, meaning people will be able to follow updates to your blog with RSS. I plan on making a post about RSS at some point, so look out for that if that caught your interest.

With this in place, here is what the header of a given blog post looks like for me:


---
title: "My first DIY web-app"
description: "Just a quick post to test the blog and brielfy talk about my first ventures into JavaScript"
author: "Luke"
date: "07/21/2024"
categories:
  - webdev
image: "images/luke-23.jpg"
comments:
    utterances:
      repo: lukmayer/site_comments
      theme: github-dark
      issue-term: url
---

The only thing that might be unexpected here is the comments field, where I configure a piece of software that allows people to comment on posts with their github accounts. I will not be covering how to set this up, but if you’re interested in having this also be part of your website look here.

Hopefully, you have a decent idea of how to achieve a blog on your webpage now!

About pages

Quarto provides some templates for easily configuring a rather stylish “About the author” page. Here is how I set up mine:

---
title: "Lukas W. Mayer"
about:
 template: jolla
 image: assets/luke-23.jpg
 links:
   - icon: github
     text: Github
     href: https://github.com/lukmayer
   - icon: medium
     text: Medium
     href: https://medium.com/@willuk
   - icon: envelope
     text: Email
     href: mailto:willuk@vivaldi.net
---

The documentation for these is super easy to understand and can be found here. There are a couple templates to select from and at the bottom I add some links to other things related to me. This YAML stuff should start to look familiar at this point ;) .

Hosting + My shell script for pushing updates to Github

If you want to host your finished site on Github, you need to initialize a local git repository in the directory that holds the rendered files. In my case that is the _site folder. Then you push these files to a Github repository that you named [yourgithubusername].github.io. Then, on the settings page of this Github repository you enable pages. If you struggle with this step, AI tools might be more helpful than the average search for this kind of debugging.

Because I have my website source files on a different repository on Github, I created a little shell script that I can push updates to both repositories with:

#!/bin/bash

# --- Build the site with Quarto ---
quarto render

# Prompt for a commit message
echo "Enter a commit message:"
read commit_message

# --- Push source files to the main repository (lukmayer/website.git) ---

# Ensure the current directory is your main project directory (not _site)
# Add and commit changes to the source repo
git add .
git commit -m "$commit_message"

git remote add origin git@github.com:lukmayer/website.git

# Push changes to the main repository (lukmayer/website.git)
# Ensure 'origin' points to the source repo (lukmayer/website.git)
git push -f origin master 


# --- Push rendered files to the GitHub Pages repository (lukmayer.github.io.git) ---

# Navigate to the _site directory (contains the rendered files)
cd _site

# Initialize a new Git repository inside _site if it doesn't exist already
if [ ! -d ".git" ]; then
    git init
    git remote add origin git@github.com:lukmayer/lukmayer.github.io.git
else
    git remote set-url origin git@github.com:lukmayer/lukmayer.github.io.git
fi

# Add and commit the rendered site files
git add .
git commit -m "$commit_message"

# Force push the rendered files to the gh-pages branch of the GitHub Pages repo
git push -f origin master:gh-pages  # Ensure that 'gh-pages' is the correct branch for GitHub Pages

# Navigate back to the root directory of the project
cd ..

The script essentially just runs a couple standard commands. First, I render my website and push the source files to their repository. After this, I change to the folder with the rendered files and force push these to the repositories that hosts the website. To use this, make sure that _site has been added to the .gitignore file in the main project directory.

With this script my workflow basically just becomes: 1) Make changes, 2) open terminal, 3) go to source directory, 4) run deploy.sh (the shell script). If you plan on using this script, keep in mind that your repository will be a different one than mine, which is further complicated by the fact that I use SSH, which will require a tutorial to set up if you are not familiar (search: “how to set up SSH with Github”).

Conclusion

So that’s it! I hope you have a good idea of how to configure a website using my approach. There are a few tricks my website uses that I didn’t cover here but I encourage you to just check my source files if you see something that catches your interest. My source repository is public, meaning that even if you found this all still a little much, with some git skills you could just grab my source code and use it as a template to get started with!

From here, you should definitely also check the Quarto documentation mentioned above. It’s currently not always extremely detailed for all possible configurations and setups but it gives you a pretty good idea of what is possible.

Find my source file repository here.

If you make a website based on my files I’d love to see it!

Thanks for reading!

Back to top