Quartz Blog Customization Log

Today I cleaned up the Quartz blog substantially. I used Claude Code for the work, and it was quite efficient.

Workflow: Claude Code + Docs First

The core of this work was “read the documentation first.” I had Claude Code explore the official Quartz documentation and the existing code before anything else. Thanks to that:

  • I reused the existing RecentNotes component instead of creating a new component
  • I discovered existing Higher-Order Components such as ConditionalRender and Footer
  • I solved the URL problem with permalink frontmatter without a custom plugin

As a result, I could implement the features I wanted with minimal code changes. It reminded me again how important it is to check the documentation before modifying a framework.

I am recording the main changes and the decision-making process.

Home Page - Articles List

I wanted the home page to show a list of posts I had written. When I looked through the Quartz documentation, I found that the RecentNotes component already existed. There was no need to build a new one; I used the built-in component.

At first I planned to show only recent posts with limit: 10, but showing the full list with infinite scroll seemed better. I considered implementing pagination, but after calculating it:

  • 13 posts currently
  • Even up to 500 posts would be about ~200KB, with almost no loading delay
  • It is a static site, so there is no server load

Conclusion: show everything with limit: 9999. Pagination would be over-engineering.

// quartz.layout.ts
Component.ConditionalRender({
  component: Component.RecentNotes({
    title: "Articles",
    limit: 9999,
    showTags: false,
    filter: (f) => f.slug !== "index",
  }),
  condition: (page) => page.fileData.slug === "index",
}),

The default footer said “Created with Quartz v4.5.2 © 2025.” It is an open-source credit, but the MIT license does not make it a legal requirement. Since this is a personal blog, I decided my own name was more appropriate.

I changed it to © {year} Beomsu Koh. The year is handled dynamically with new Date().getFullYear().

I also added social links:

  • GitHub, LinkedIn, X, Medium, Tistory, Email

Comments (Giscus)

I had enabled comments with Giscus, but I felt reactions (emoji reactions) were unnecessary. I kept comments and disabled reactions.

Component.Comments({
  provider: "giscus",
  options: {
    repo: "Goberomsu/Quartz-CV",
    repoId: "R_kgDOMzvCAQ",
    category: "Announcements",
    categoryId: "DIC_kwDOMzvCAc4Civ7w",
    reactionsEnabled: false,  // reactions 비활성화
  },
}),

This was the most important change. When the folder structure changed, the URL changed too. For example, moving InBox/my-article to Articles/my-article would break the existing link.

I considered two options:

  1. Use a fixed prefix such as /posts/
  2. Use permalink for flat URLs

Conclusion: Flat URL is better.

  • berom.net/my-article is shorter and cleaner than berom.net/posts/my-article
  • Lower depth is also better for SEO
  • If side projects are separated with subdomains such as project.berom.net, there is no collision

I also considered Korean URLs, but once they are UTF-8 encoded, they become long strings like %EC%82%AC%EB%9E%91…. English slugs are better for SEO.

Rules:

  • permalink must be in English
  • Use kebab-case: my-article-title
  • If the title is already in English, keep it as-is
# 예시
---
title: 사랑은 사랑이라서
permalink: love-is-love
---