This site was built using Quartz 4.0.

Learning a new website creation system is challenging, so below, I’ll detail my process for figuring out how to customize different components.

Adding more Google Fonts


I wanted the page title to display in a different font than all of the other headers. In quartz.config.ts, I first tried changing the header key-value pair to take multiple arguments:

theme: {
      typography: {
        header: ["Kalam", "Bilbo Swash Caps"],
        body: "Source Sans Pro",
        code: "IBM Plex Mono",

Didn’t work. Then I tried adding another key-value pair:

theme: {
      typography: {
        siteTitle: "Bilbo Swash Caps", // NEW
        header: "Kalam",
        body: "Source Sans Pro",
        code: "IBM Plex Mono",

Didn’t work. I knew that to embed Google fonts on a page, some embed code was needed. From the Google Fonts documentation, this would look something like:

<link rel="preconnect" href="">
<link rel="preconnect" href="" crossorigin>
<link href=";400;700&display=swap" rel="stylesheet">

This would go in the <head> section of an HTML file. I needed to figure out how the typograph parameters were getting read into the <head> section, so I looked in quartz/components and found Head.tsx. In this file I found:

return (
        <meta charSet="utf-8" />
        {cfg.theme.cdnCaching && cfg.theme.fontOrigin === "googleFonts" && (
            <link rel="preconnect" href="" />
            <link rel="preconnect" href="" />
            <link rel="stylesheet" href={googleFontHref(cfg.theme)} />

From this, I learned that the googleFontHref() function was the driver. Looking at the top of Head.tsx, I saw that this function was in the file quartz/util/theme.ts:

import { googleFontHref } from "../util/theme"


Inside quartz/util/theme.ts, I modified the googleFontHref() function:

export function googleFontHref(theme: Theme) {
  const { code, header, body, siteTitle } = theme.typography
  return `${code}&family=${header}:wght@400;700&family=${body}:ital,wght@0,400;0,600;1,400;1,600&family=${siteTitle}&display=swap`
Original function
export function googleFontHref(theme: Theme) {
  const { code, header, body } = theme.typography
  return `${code}&family=${header}:wght@400;700&family=${body}:ital,wght@0,400;0,600;1,400;1,600&display=swap`

This required ensuring that siteTitle was a parameter in quartz.config.ts:

theme: {
      typography: {
        siteTitle: "Bilbo Swash Caps",
        header: "Kalam",
        body: "Source Sans Pro",
        code: "IBM Plex Mono",

Inside quartz/util/theme.ts, I also modified the joinStyles() function to also include siteTitleFont as a new variable that could be referenced in style sheets:

export function joinStyles(theme: Theme, ...stylesheet: string[]) {
  return `
:root {
  --headerFont: "${theme.typography.header}", ${DEFAULT_SANS_SERIF};
  --bodyFont: "${theme.typography.body}", ${DEFAULT_SANS_SERIF};
  --codeFont: "${theme.typography.code}", ${DEFAULT_MONO};
  --siteTitleFont: "${theme.typography.siteTitle}";

I used siteTitleFont in quartz/styles/custom.scss:

.page-title {
  font-size: 2.5rem;
  font-family: var(--siteTitleFont);

Left menu bar navigation

I didn’t want to have Component.Explorer() so I created a static component that was just a list of links as NavMenu.tsx:

import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
export default ((userOpts?: Options) => {
  function NavMenu(props: QuartzComponentProps) {
    return (
      <div class="navmenu">
        <p><a href="/writing">Garden</a></p>
        <p><a href="/teaching">Teaching</a></p>
        <p><a href="/talks">Talks</a></p>
        <p><a href="/cv.pdf">CV</a></p>
        <p><a href="/colophon">Colophon</a></p>
  return NavMenu
}) satisfies QuartzComponentConstructor

Changing date display

I wanted the metadata beneath the article title to look something like:

Last tended   May 22, 2024   ╌ ❖ ╌   1 min read

The “Last tended”, separator between the date and “X min read”, and the spacing between each of these components needed to be added.

There are three possible types (as found in quartz/plugins/transformers/lastmod.ts):

  • "created": corresponds to frontmatter date
  • "modified": corresponds to frontmatter lastmod or updated
  • "published": corresponds to frontmatter publishDate

I updated the defaultDateType in quartz.config.ts to be "modified".

In quartz/components/ContentMeta.tsx, I made the following changes:

const defaultOptions: ContentMetaOptions = {
  showReadingTime: true,
  showComma: false, // Changed to false
if (fileData.dates) {
  segments.push("Last tended") // New
  segments.push(formatDate(getDate(cfg, fileData)!, cfg.locale))
// Display reading time if enabled
if (options.showReadingTime) {
  const { minutes, words: _words } = readingTime(text)
 . const displayedTime = i18n(cfg.locale).components.contentMeta.readingTime({
    minutes: Math.ceil(minutes),
  segments.push("╌ ❖ ╌") // new
const segmentsElements = => <span class="content-meta-comp">{segment}</span>) // Added class="content-meta-comp"

Then I added the following to quartz/styles/custom.scss:

.content-meta-comp {
  font-family: var(--siteTitleFont);
  padding-right: 0.6em; /* This adds ths spacing */

Custom domain