Building this Website

website
vscode
quarto
git
makefile
Published

December 18, 2025

This post summarizes the steps taken to build this website.

Goals

I was inspired by Fabien Sanglard’s excellent website, and I set similar goals for my website:

  • Simple, pure, ultra-responsive, no unnecessary friction.
  • Low effort to set up and maintain.
  • Flexible, not locked to a particular platform or technical fad.
  • Flexibility as an authoring platform, so material can be published online, offline, to books, etc.

So naturally, I looked into how Fabien built his website. And it looks like I wasn’t alone, as there is a dedicted post about it!

The Solution

I’ve settled on the following:

  • Quarto for turning qmd files into html. It can do websites, blogs, but also books from the same source content. qmd files are similar to te md fileformat, so it’s fairly readable, flexible and simple to us. It’s also well suited for programming focused documentation and code.

  • VSCode for editing the website. It’s already my primary IDE on Mac, it support Git well. Quarto also has a a VSCode extension with live preview. It makes editing fairly easy, I can easily work on any computer and update the website in seconds.

  • Github for storing the website, on a private repository. I’m using 2 branches: master for development, release for live publishing the website.

  • Cloudflare for domain, dns and hosting. One website and account to do it all. It directly syncs to Git, which means all I have to do to update the website is to push into my release branch on my git repo. Cloudflare picks it up automatically and the website is updated and live!

  • A custom Makefile1 to automatically build the website, preview, commit and publish. To automate the whole process.

Footnotes

  1. makefile used to build/preview/publish this website.

    # Makefile for /learn/code/play
    
    # -------- Configuration --------
    SITE_DIR      := _site
    MAIN_BRANCH   := master
    DEPLOY_BRANCH := release   # Cloudflare deploys from this branch
    
    .DEFAULT_GOAL := help
    
    .PHONY: preview build open serve commit publish help
    
    # Build site and open it in browser
    preview: build open        ## Build site and open in browser
    
    # Build the static site into $(SITE_DIR)
    build:                     ## Build static site ($(SITE_DIR)/)
        rm -rf $(SITE_DIR)
        quarto render
    
    # Open the local built site (macOS 'open')
    open:                      ## Open $(SITE_DIR)/index.html in browser
        open $(SITE_DIR)/index.html
    
    # Start Quarto dev server (watch mode) - this holds the terminal
    serve:                     ## Start Quarto dev server (watch mode)
        quarto preview
    
    # Commit everything with MESSAGE="your commit message"
    # ensures we are on MAIN_BRANCH before committing
    commit:                    ## Commit changes: make commit MESSAGE="Your message"
        @BRANCH=$$(git rev-parse --abbrev-ref HEAD); \
        if [ "$$BRANCH" != "$(MAIN_BRANCH)" ]; then \
            echo "ERROR: You are on branch '$$BRANCH'. Commits are only allowed on '$(MAIN_BRANCH)'."; \
            exit 1; \
        fi; \
        if [ -z "$$MESSAGE" ]; then \
            echo "Usage: make commit MESSAGE=\"Your commit message\""; \
            exit 1; \
        fi; \
        git add .; \
        git commit -m "$$MESSAGE"; \
        git push origin $(MAIN_BRANCH); \
        git status
    
    # Publish:
    #  - ensure we're on MAIN_BRANCH and clean
    #  - pull latest MAIN_BRANCH
    #  - render site on MAIN_BRANCH, commit _site there
    #  - fast-forward DEPLOY_BRANCH to MAIN_BRANCH
    publish:                   ## Render on $(MAIN_BRANCH), fast-forward $(DEPLOY_BRANCH), and push
        @set -e; \
        BRANCH=$$(git rev-parse --abbrev-ref HEAD); \
        if [ "$$BRANCH" != "$(MAIN_BRANCH)" ]; then \
            echo "ERROR: You must be on '$(MAIN_BRANCH)' to publish (currently on '$$BRANCH')."; \
            exit 1; \
        fi; \
        if ! git diff-index --quiet HEAD --; then \
            echo "Working tree is dirty. Commit or stash changes before publishing."; \
            exit 1; \
        fi; \
        echo "Updating $(MAIN_BRANCH) from origin..."; \
        git pull origin $(MAIN_BRANCH); \
        echo "Fast-forwarding $(DEPLOY_BRANCH) to $(MAIN_BRANCH)..."; \
        git checkout $(DEPLOY_BRANCH); \
        git pull origin $(DEPLOY_BRANCH); \
        git merge --ff-only $(MAIN_BRANCH); \
        git push origin $(DEPLOY_BRANCH); \
        echo "Switching back to $(MAIN_BRANCH)..."; \
        git checkout $(MAIN_BRANCH); \
        git status
    
    # Show available commands
    help:                      ## Show this help message
        @echo "Available commands:"
        @grep -E '^[a-zA-Z0-9_-]+:.*##' Makefile | awk 'BEGIN {FS = ":.*##"}; {printf "  %-10s %s\n", $$1, $$2}'
    ↩︎