How I Built This Blog

web
Author

Phlo

Published

September 12th

A short walkthrough on the tools, commands and code used to build this blog with Quarto.

Initial Setup

Install Quarto

Set up GitHub repository

  • Create new repository on GitHub named USERNAME.github.io
    • Any repo name other than USERNAME.github.io will be shown as USERNAME.github.io/reponame/ on the web
  • Clone it to local machine

Initialize Quarto Blog Template

quarto create-project --title BLOG-NAME --type website --template blog

Change output-dir to gh-pages

diff --git a/_quarto.yml b/_quarto.yml
--- a/_quarto.yml
+++ b/_quarto.yml
@@ -1,5 +1,6 @@
 project:
   type: website
+  output-dir: gh-pages
 
 website:
   title: "BLOG-NAME"
TipCreate a .nojekyll file

You can use the CLI to create the .nojekyll file:

Unix:

touch .nojekyll

Windows:

type NUL > .nojekyll

Add 2 folders to .gitignore

/.venv
/gh-pages

Create requirements.txt for Quarto venv

mureq==0.2.0

Push it to GitHub

git add .
git commit -S -m "initialize quarto blog template"
git push

One time publish command

quarto publish gh-pages

Change repo Pages settings

Go to https://github.com/USERNAME/USERNAME.github.io/settings/pages

  • Repo -> Settings -> Pages -> Source -> Branch: gh-pages
  • Save

Configure GitHub Actions

  • mkdir .github/workflows
  • Add a workflow file to .github/workflows/publish.yml
on:
  workflow_dispatch:
  push:
    branches: main

name: Quarto Publish

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Quarto
        uses: quarto-dev/quarto-actions/setup@v2

      - name: Install Python and Dependencies
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
          cache: 'pip'
      - run: pip install jupyter
      - run: pip install -r requirements.txt

      - name: Render and Publish
        uses: quarto-dev/quarto-actions/publish@v2
        with:
          target: gh-pages
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Render and preview

quarto preview --render all

Customization

Customize the look of the blog

diff --git a/_quarto.yml b/_quarto.yml
--- a/_quarto.yml
+++ b/_quarto.yml
@@ -13,7 +13,7 @@ website:
         href: https://twitter.com
 format:
   html:
-    theme: cosmo
+    theme: lux
     css: styles.css
diff --git a/about.qmd b/about.qmd
--- a/about.qmd
+++ b/about.qmd
@@ -2,7 +2,7 @@
 title: "About"
 image: profile.jpg
 about:
-  template: jolla
+  template: broadside
   links:
     - icon: twitter
       text: Twitter
diff --git a/index.qmd b/index.qmd
--- a/index.qmd
+++ b/index.qmd
@@ -8,7 +8,7 @@ listing:
   sort-ui: false
   filter-ui: false
 page-layout: full
-title-block-banner: true
+title-block-banner: false
 ---

Custom Domain

Verify the domain within your username or organization using these steps.

For users:

https://github.com/settings/pages

For organizations:

https://github.com/organizations/ORGANIZATION_NAME/settings/pages
https://github.com/organizations/ORGANIZATION_NAME/settings/domains

Check GitHub docs for managing a custom domain to be sure the following IPs are accurate.

Namecheap

If your domain registrar is Namecheap, here are the steps today:

Log in to Namecheap, find your domain name, click Manage

  • Go to Advanced DNS

  • Click Add New Record

  • Select TXT for type

  • Add the Host: _github-pages-challenge-USERNAME

(Use the exact subdomain GitHub gives you)

Warning

Do not add .domain.com to the host; Namecheap automatically appends the domain name.

  • Add the Value: 0xhash5tring

(Use the exact value GitHub gives you)

  • Set the TTL to 1 min (shorter TTL helps propagation when testing)
  • Check the green checkmark to save the record
TipCheck DNS Propagation Status

You can use the CLI to check if your TXT record has propagated:

Unix:

dig TXT _github-pages-challenge-USERNAME.domain.com

Windows:

nslookup -type=txt _github-pages-challenge-USERNAME.domain.com
Note

It should only take a few minutes for the record to propagate. If it takes longer, something went wrong.


Now it’s time to add four A records to Namecheap.

You need to add A records for the following IPs: 185.199.108.153, 185.199.109.153, 185.199.110.153, 185.199.111.153

  • Click Add New Record
  • Select A for type
  • Add the Host: @
  • Add the Value: 185.199.108.153
  • Set the TTL to 1 min (shorter TTL helps propagation when testing)
  • Check the green checkmark to save the record

Repeat for the other three IPs:

  • 185.199.109.153
  • 185.199.110.153
  • 185.199.111.153

Let’s also add a CNAME record for www to point to USERNAME.github.io

  • Click Add New Record
  • Select CNAME for type
  • Add the Host: www
  • Add the Value: USERNAME.github.io
  • Set the TTL to 1 min (shorter TTL helps propagation when testing)
  • Check the green checkmark to save the record

Cloudflare

If your domain registrar is not Cloudflare but you want to use their protection, sign up for a free account and point your nameservers to Cloudflare using the quick start guide.

If your domain registrar is Cloudflare, here are the steps today:

Log in to Cloudflare, locate your domain name on the left hand side, click it to ensure you’re on the correct domain

  • Click DNS in the left hand sidebar

  • Click Records

  • Click the blue Add record button

  • Select TXT for type

  • Add the Name: _github-pages-challenge-USERNAME

(Use the exact subdomain GitHub gives you)

  • Add the Content: 0xhash5tring

(Use the exact value GitHub gives you)

  • Set the TTL to 1 min (shorter TTL helps propagation when testing)
  • Click the blue Save button at the bottom right
TipCheck DNS Propagation Status

You can use the CLI to check if your TXT record has propagated:

Unix:

dig TXT _github-pages-challenge-USERNAME.domain.com

Windows:

nslookup -type=txt _github-pages-challenge-USERNAME.domain.com
Note

It should only take a few minutes for the record to propagate. If it takes longer, something went wrong.


Now it’s time to add four A records to Cloudflare.

You need to add A records for the following IPs: 185.199.108.153, 185.199.109.153, 185.199.110.153, 185.199.111.153

  • Click the blue Add record button
  • Select A for type
  • Add the Name: @
  • Add the Content: 185.199.108.153
  • Ensure the proxy status is set to “DNS only” (gray cloud icon) - GitHub Pages requires DNS-only mode
  • Click the blue Save button

Repeat for the other three IPs:

  • 185.199.109.153
  • 185.199.110.153
  • 185.199.111.153

Let’s also add a CNAME record for www to point to USERNAME.github.io

  • Click the blue Add record button
  • Select CNAME for type
  • Add the Name: www
  • Add the Content: USERNAME.github.io
  • Ensure the proxy status is set to “DNS only” (gray cloud icon) - GitHub Pages requires DNS-only mode
  • Click the blue Save button

Allow a few moments for the DNS to propagate then Go to https://github.com/USERNAME/USERNAME.github.io/settings/pages

  • Add your custom domain (apex domain meaning no subdomain just example.com)
  • Save

Once the DNS check is successful move onto doing Google Analytics and Search Console.

You will need to add another TXT record to verify ownership of website for Search Console.

Google Analytics

Log in to Google Analytics and click the Admin cog wheel in the lower left corner.

Click the + button in the top left corner and select Create Account inside of this Account will be your new GA property.

Most of this process is very straightforward other than maybe the naming conventions.

TipNaming Conventions

When creating your Google Analytics account and property, follow these naming conventions:

Account Name:

  • Use proper case (capitalize each word), e.g., Company Name or Brand Identity
  • Can be all one word if it looks good, otherwise separate words with proper capitalization

Property Name:

  • Use the apex domain name (no www, no https://, no subdomains)
  • All lowercase, e.g., companyname.info or brandidentity.com

Stream Name:

  • For simple single-domain setups, use the apex domain name (all lowercase) brandidentity.com
  • Can be more descriptive if you have multiple streams (e.g., web, ios, android)

Measurement ID:

  • This is the G-XXXXXXXXXX code you’ll add to your _quarto.yml file
  • Found in the web stream details after creating the data stream

You mostly want to take the G-XXXXXXXXXX code and add it to the _quarto.yml file so Analytics can track the website.

Search Console

Log in to Google Analytics and click the Admin cog wheel in the lower left corner

  • Admin > Product Links > Search Console Links > Add Product Link

  • Choose Search Console property > Add property

Open a new tab and log in to domain registrar (again) to add a TXT record to verify ownership of website for Search Console

Log in to your registrar:

Namecheap

  • Find your domain name, click Manage

  • Go to Advanced DNS

  • Click Add New Record

  • Select TXT for type

  • Add the Host: @

  • Add the Value: google-site-verification=hash5tring

  • Set the TTL to 1 min (shorter TTL helps propagation when testing)

  • Check the green checkmark to save the record

Cloudflare

  • Find your domain name in the left sidebar and click it

  • Click DNS in the left hand sidebar

  • Click Records

  • Click the blue Add record button

  • Select TXT for type

  • Add the Name: @

  • Add the Content: google-site-verification=hash5tring

  • Set the TTL to 1 min (shorter TTL helps propagation when testing)

  • Click the blue Save button at the bottom right


Once verified return to Google Analytics

  • Choose Search Console property > Select Web Stream > Review and Submit

Configuration

Here is an example of what your _quarto.yml file could look like once everything is set up:

project:
  type: website
  output-dir: gh-pages
  preview:
    port: 5678
website:
  title: "example.com"
  navbar:
    right:
      - about.qmd
      - icon: github
        href: https://github.com/USERNAME
      - icon: twitter
        href: https://twitter.com/USERNAME
  site-url: https://example.com
  google-analytics: G-XXXXXXXXXX
  twitter-card: true
  open-graph: true
ImportantDon’t Forget!

Before moving on, return to your domain registrar and reset all of the TTLs to Automatic.