astro-koharu Usage Guide

发表于 2025-12-29 21:55 更新于 2026-02-18 02:40 3391 字 17 min read

cos avatar

cos

FE / ACG / 手工 / 深色模式强迫症 / INFP / 兴趣广泛养两只猫的老宅女 / remote

A complete usage guide for the astro-koharu blog, including quick start, configuration, article system, UI features, and more

This article has been machine-translated from Chinese. The translation may contain inaccuracies or awkward phrasing. If in doubt, please refer to the original Chinese version.

A complete guide for the astro-koharu blog system to help you get started quickly and make the most of all features.

Quick Start

Project Overview

astro-koharu is a modern blog system built on Astro 5.x, migrated from Hexo, with design inspiration and motivation drawn from the Shoka theme. Feel free to fork and create your own theme.

Core Features:

  • Built on Astro 5.x, static site generation with excellent performance
  • Elegant dark/light theme toggle
  • Full-site search powered by Pagefind, no backend required
  • Complete Markdown enhancements (GFM, code highlighting, auto-generated table of contents)
  • Flexible multi-level category and tag system (migrated from the Shoka theme; may become optional in the future)
  • Multiple article series support (weekly digest, book excerpts, and other custom series with custom URL slugs)
  • Responsive design
  • Draft and pinning features
  • Reading progress bar and estimated reading time
  • Mobile article reading header
  • Blogroll and archive pages
  • Multi-language support (i18n)
  • RSS feed support
  • LQIP (Low Quality Image Placeholders)
  • Christmas special effects (toggleable)

Local Development

# Clone the project
git clone https://github.com/cosZone/astro-koharu.git
cd astro-koharu

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Build for production
pnpm build

# Preview production build
pnpm preview

Quick Deployment

Deploy with one click using Vercel:

Deploy with Vercel

Basic Configuration

Site Configuration

Edit the config/site.yaml file to configure basic site information:

# =============================================================================
# 站点基础信息
# =============================================================================
site:
  title: 余弦の博客 # 网站标题
  alternate: cosine # 英文短名(用作 logo 文本)
  subtitle: WA 的一声就哭了 # 副标题
  name: cos # 站点作者简称
  description: FE / ACG / 手工 / 深色模式强迫症 / INFP # 站点简介
  avatar: /img/avatar.webp # 头像路径
  showLogo: true # 是否显示 logo
  author: cos # 文章作者
  url: https://blog.cosine.ren/ # 站点域名
  startYear: 2020 # 站点创建年份
  keywords: # SEO 关键词
    - cos
    - cosine
    - 博客
    - 技术
    - 前端

Local Lightweight CMS App

This project provides a standalone CMS management application that supports article management, in-browser editing, Markdown preview, and more.

Start the CMS:

# First-time use requires installing dependencies
pnpm cms:install

# Start CMS (default port 4322)
pnpm cms

The CMS provides these features:

  • Article dashboard: View article stats, category distribution, recent updates
  • In-browser editor: Rich text editing based on BlockNote with Markdown support
  • Draft/publish toggle: One-click article status switching
  • Pinning management: Quick pin/unpin articles
  • Create articles: Interactive article creation with auto-generated frontmatter

Local Editor Jump

The edit button on article pages supports one-click jump to your local editor (VS Code / Cursor / Zed, etc.).

Configuration file: dev section of config/site.yaml

dev:
  localProjectPath: "/Users/yourname/path/to/astro-koharu" # 本地项目绝对路径
  contentRelativePath: "src/content/blog" # 博客内容目录
  editors:
    - id: vscode
      name: VS Code
      icon: devicon-plain:vscode # 可从 https://icon-sets.iconify.design/ 搜寻图标
      urlTemplate: "vscode://file{path}"
    - id: cursor
      name: Cursor
      icon: simple-icons:cursor
      urlTemplate: "cursor://file{path}"
    - id: zed
      name: Zed
      icon: simple-icons:zedindustries
      urlTemplate: "zed://file{path}"

Configuration notes:

  • localProjectPath must be an absolute path on your machine; otherwise the correct file path cannot be generated
  • urlTemplate supports the placeholder, which gets replaced with the file’s full path
  • Once configured, article pages will display an edit button that directly opens the file in your local editor

Featured Categories Configuration:

Featured category cards displayed at the bottom of the homepage:

featuredCategories:
  - link: life # 分类链接(对应 category_map)
    label: 随笔 # 显示名称
    image: /img/cover/2.webp # 封面图片
    description: 生活记录、年度总结等 # 描述
  - link: note/front-end
    label: 前端笔记
    image: /img/cover/1.webp
    description: 前端相关的笔记
  # ... more categories

Multiple Article Series Configuration:

Configure featured series (such as weekly digests, book excerpts, etc.) with multiple series support, each having its own page and custom URL:

featuredSeries:
  - slug: weekly # URL path: /weekly (required, used as page route)
    categoryName: 周刊 # Category name (used to match articles)
    label: FE Bits # Display label
    fullName: FE Bits 前端周周谈 # Full name
    description: | # Description (supports multi-line)
      之前在自己的频道进行一些输出,于是有了这个周刊!
      更新时间期望是在每周天
    cover: /img/weekly_header.webp # Cover image
    enabled: true # Whether enabled
    icon: ri:newspaper-line # Navigation icon (optional)
    highlightOnHome: true # Whether to highlight latest article on homepage (optional, default true)
    links: # Related links
      github: https://github.com/your-username/your-repo
      rss: /rss.xml

  - slug: reading # URL path: /reading
    categoryName: 书摘
    label: 读书笔记
    fullName: 我的读书笔记
    description: 读书摘录与感悟
    cover: /img/reading_header.webp
    enabled: true
    highlightOnHome: false # This series is not highlighted on homepage

Field descriptions:

FieldRequiredDescription
slugYesURL path, e.g., weekly maps to /weekly
categoryNameYesCategory name used to match articles
labelNoDisplay label (defaults to categoryName)
enabledNoWhether this series is enabled (default true)
fullNameNoFull name (used for page title)
descriptionNoSeries description
coverNoCover image path
iconNoNavigation icon (Iconify format)
highlightOnHomeNoWhether to highlight latest article on homepage (default true)
linksNoRelated links (github, rss, etc.)

Social Media Configuration

Configure social media links in config/site.yaml:

social:
  github:
    url: https://github.com/your-username
    icon: ri:github-fill # Iconify icon name
    color: "#191717" # Theme color
  bilibili:
    url: https://space.bilibili.com/your-uid
    icon: ri:bilibili-fill
    color: "#da708a"
  email:
    url: mailto:your@email.com
    icon: ri:mail-line
    color: "#55acd5"
  rss:
    url: /rss.xml
    icon: ri:rss-line
    color: "#ff6600"
  # ... more platforms

Supported platforms: GitHub, Twitter, Bilibili, NetEase Cloud Music, Email, RSS, etc. See the config/site.yaml file for complete configuration.

Customize the navigation menu in config/site.yaml:

navigation:
  - name: 首页
    path: /
    icon: fa6-solid:house-chimney
  - name: 周刊
    path: /weekly # Corresponds to slug: weekly in featuredSeries
    icon: ri:newspaper-line
  - name: 读书笔记
    path: /reading # Corresponds to slug: reading in featuredSeries
    icon: ri:book-open-line
  - name: 文章
    icon: ri:quill-pen-ai-fill
    children: # Supports nested submenus
      - name: 分类
        path: /categories
        icon: ri:grid-fill
      - name: 标签
        path: /tags
        icon: fa6-solid:tags
      - name: 归档
        path: /archives
        icon: ri:archive-2-fill
  - name: 友链
    path: /friends
    icon: ri:links-line
  - name: 关于
    path: /about
    icon: fa6-regular:circle-user

Note: Series page paths use the format /{slug} and must match the slug field configured in featuredSeries.

Category Mapping Configuration

Configure the mapping from Chinese category names to URL slugs in config/site.yaml:

# =============================================================================
# Category Map
# Maps Chinese category names to URL-friendly English slugs
# =============================================================================
categoryMap:
  # Primary categories
  随笔: life
  笔记: note
  工具: tools
  周刊: weekly # For category page /categories/weekly
  书摘: reading # For category page /categories/reading
  # Secondary categories (for nested paths)
  前端: front-end
  # Add more as needed:
  # 后端: back-end
  # 算法: algorithm

This way, the URL for the “Life” category will be /categories/life instead of /categories/随笔.

Note: categoryMap is only used for URL mapping on category pages (/categories/*). Series page URLs (like /weekly, /reading) are configured separately via the slug field in featuredSeries.

Article System

Creating Articles

Method 1: Using the Koharu CLI (Recommended)

Use the interactive CLI tool to quickly create articles:

pnpm koharu new post

The CLI tool will guide you through entering the title, category, tags, and other information, automatically generating the frontmatter and markdown file.

Method 2: Manual Creation

Create Markdown files under the src/content/blog/ directory. The directory structure affects the article’s categorization:

src/content/blog/
├── life/              # Life category
│   └── 2024-life-review.md
├── note/
│   ├── front-end/     # Notes > Front-end
│   │   └── react/
│   │       └── React学习小记.md
│   └── algorithm/     # Notes > Algorithm
│       └── 动态规划学习笔记.md
└── tools/             # Tools category
    └── vscode插件推荐.md

Frontmatter Field Reference

Each article must begin with YAML frontmatter:

Required fields:

---
title: Article Title # Required
date: 2024-12-06 # Required, publication date
---

Common optional fields:

---
title: Article Title
date: 2024-12-06
updated: 2024-12-15 # Last updated time (optional, displayed on article page when present)
description: Article summary # Used for SEO and list display; auto-uses AI summary or first 150 chars if omitted
link: custom-url-slug # Custom URL (defaults to filename)
cover: /img/cover/1.webp # Cover image
tags: # Tag list
  - JavaScript
  - React
categories: # Categories (see detailed explanation below)
  - 笔记
subtitle: Subtitle # Article subtitle
catalog: true # Whether to show table of contents (default true)
tocNumbering: true # Whether to show TOC numbering (default true)
draft: false # Whether it's a draft (default false)
sticky: false # Whether to pin to top (default false)
excludeFromSummary: false # Whether to exclude from AI summaries and similarity calculations (default false, recommended true for series articles)
math: false # Whether to enable math formula rendering (default false, enables KaTeX when true)
quiz: false # Whether to enable quiz interaction (default false, supports four question types when enabled)
password: mySecret # Full article encryption password (optional, requires password to read when set)
---

About the description field:

Article description priority: handwritten description > AI auto-summary > first 150 chars of Markdown body

  • It’s recommended to write descriptions for important articles for better SEO
  • If the description is omitted, the system will automatically use AI-generated summaries (requires running pnpm generate:summaries)
  • If there’s neither a handwritten description nor an AI summary, the first 150 characters of the article body are automatically extracted

About the link field (Custom URL):

Important: The link field is automatically converted to lowercase to maintain URL consistency and standardization.

  • Normalization behavior: Whether you enter MyPost, myPost, or mypost, the final URL will be /post/mypost
  • Filename case-insensitive: Article filenames can use any casing (e.g., MyPost.md); the system handles it automatically
  • AI summaries and similarity: Keys in generated summaries.json and similarities.json are also unified to lowercase
  • Best practice: Use lowercase and hyphens directly (e.g., my-awesome-post) to avoid confusion
# Recommended
link: my-awesome-post  # URL: /post/my-awesome-post

# Will be converted to lowercase
link: MyAwesomePost    # URL: /post/myawesomepost (NOT /post/MyAwesomePost)
link: My-Awesome-Post  # URL: /post/my-awesome-post

If the link field is omitted, the system uses the filename (also converted to lowercase):

# File: src/content/blog/MyPost.md
# Omitting link field → URL: /post/mypost

Category System

astro-koharu supports flexible category configuration:

Single-level category:

categories:
  - 工具 # or ['工具']

Corresponding URL: /categories/tools (mapped via categoryMap)

Multi-level nested categories:

categories:
  - [笔记, 前端, React]

This creates a hierarchy: Notes > Front-end > React

Corresponding URL: /categories/note/front-end/react

Tag System

Tags are flat and don’t support hierarchies:

tags:
  - JavaScript
  - TypeScript
  - 学习笔记

All tags are displayed on the /tags page. Clicking a tag shows all articles under that tag.

Draft Feature

Set draft: true to mark an article as a draft:

---
title: Unfinished Article
draft: true
---

Behavior:

  • Local development (pnpm dev): Drafts are visible, with a “DRAFT” badge in the upper right of article cards
  • Production build (pnpm build): Drafts are automatically filtered out and won’t appear in any lists

Pinning Feature

Set sticky: true to pin an article:

---
title: Important Announcement
sticky: true
---

Behavior:

  • Pinned articles appear in the “Pinned Articles” section on the homepage
  • Pinned articles are sorted by date (newest first)
  • Does not affect sorting on other pages (categories, tags, archives)

Series Articles

Series configured with featuredSeries (see Basic Configuration) will:

  1. Have a dedicated series page (URL determined by slug, e.g., /weekly, /reading)
  2. Not appear in the regular article list (/posts)
  3. If the series has highlightOnHome: true, the latest article will be highlighted on the homepage

Example:

---
title: FE Bits Vol.16
categories:
  - 周刊 # Matches a featuredSeries categoryName
excludeFromSummary: true # Optional: exclude from AI summary generation
---
---
title: 《代码大全》读书笔记
categories:
  - 书摘 # Matches another featuredSeries categoryName
---

Tip: An article’s categories field needs to match the categoryName of a series in featuredSeries to be included in that series.

Standalone Pages

Beyond blog articles, you can create .md files in the src/pages/ directory to add standalone pages (like “About”, “Music”, etc.). These pages use the PageLayout.astro layout and support full Markdown enhancements.

Creating a standalone page:

Create a new .md file in the src/pages/ directory:

---
layout: ../layouts/PageLayout.astro
title: "歌单"
description: "我喜欢的音乐"
coverTitle: "我的歌单"
comments: false
---

页面内容...

Frontmatter fields:

FieldRequiredDescription
layoutYesFixed to ../layouts/PageLayout.astro
titleYesPage title (for browser tab)
descriptionNoPage description (for SEO)
coverTitleNoTitle displayed on cover (defaults to title)
commentsNoWhether to show comment section (default true)

Adding a navigation entry:

Add the corresponding menu item in the navigation section of config/site.yaml:

navigation:
  # ...
  - name: 歌单
    path: /music
    icon: ri:music-2-fill

Tip: All .md files under src/pages/ are automatically covered by Koharu CLI’s backup feature — no additional configuration needed.

UI Features

Theme Toggle

Click the sun/moon icon in the upper right corner to toggle between dark and light modes.

Code highlighting:

  • Light mode: github-light
  • Dark mode: github-dark

Static site search powered by Pagefind, no backend server required.

Open search:

  • Click the search icon in the navigation bar
  • Shortcut: Cmd/Ctrl + K

Features:

  • Chinese word segmentation support
  • Real-time search results
  • Keyword highlighting in matches
  • Article summary and metadata display

Article Reading Features

Table of Contents (TOC):

  • Automatically extracts article headings (h2-h6) to generate a table of contents
  • Uses CSS counters to automatically add hierarchical numbering (e.g., 1., 1.1., 1.1.1.)
  • Supports disabling numbering via the tocNumbering: false frontmatter field
  • Click TOC items to jump to the corresponding section
  • Auto-highlights the current section while scrolling
  • Desktop: displayed in the right sidebar; Mobile: collapsible

TOC numbering control:

---
title: My Article
tocNumbering: false # Disable TOC numbering (default is true)
---
  • By default, all articles display hierarchical numbering in the TOC
  • Setting tocNumbering: false disables numbering for a specific article
  • Numbering is implemented via CSS counters with zero runtime overhead
  • Applies to both desktop sidebar and mobile dropdown TOC

Reading progress bar:

  • Displayed at the top of the page showing reading progress
  • Updates in real-time based on current reading position

Heading anchor links:

  • Every heading gets an auto-generated ID
  • Hovering over a heading reveals a # link icon
  • Clicking copies the URL with the anchor

Series article navigation:

The bottom of an article shows previous/next articles in the same series:

  • Auto-grouped by the deepest category level
  • Sorted by publication date
  • Displays article title and cover

Reading time estimate:

Article cards display estimated reading time (calculated based on word count).

Mobile article reading header:

On mobile (at most 992px) when reading articles, the top navigation bar shows a header optimized for reading:

  • Circular reading progress - A circular progress bar showing current reading progress in real-time
  • Current section title - Displays the current H2/H3 section title with smooth transition animations
  • Expandable TOC - Tap the title area to expand the full article table of contents for quick navigation

Features:

  • Auto-updates the current section while scrolling
  • Supports prefers-reduced-motion for reduced animations

Responsive Design

Desktop:

  • Two-column layout (main content + sidebar)
  • Fixed navigation bar
  • Floating table of contents

Tablet:

  • Adaptive layout adjustments
  • Simplified sidebar

Mobile:

  • Single-column layout
  • Drawer-style navigation (hamburger menu)
  • Collapsible table of contents
  • Touch-optimized interactions
  • Article page dedicated reading header (progress circle + current title + expandable TOC)

Special Features

Due to the length of this guide, please refer to the Chinese version for the complete special features section, which covers: Series Article System, Archive Page, Blogroll System, LQIP, Related Article Recommendations, AI Auto Summaries, Christmas Special Effects, Site Announcement System, Markdown Enhancements (Mermaid, Infographic, Shoka-compatible syntax, Content Encryption, Quiz System, Math Formulas, Code Block Enhancements), Multi-language Support (i18n), RSS Feed, and Analytics.

The configuration and usage for all these features remain the same as described in the Chinese version. Code blocks, YAML configuration, and technical terms are identical across both versions.

Comparison with Hexo/Shoka Theme

Retained Features

  • Categories and tag system
  • Article pinning
  • Dark/light theme toggle
  • Responsive design
  • Blogroll page
  • Archive page

Improvements

Performance:

  • Static Site Generation (SSG) for faster loading
  • On-demand JavaScript loading
  • Image optimization

Developer Experience:

  • TypeScript type safety
  • Hot Module Replacement (HMR)
  • Modern development toolchain

Feature Enhancements:

  • More powerful full-site search (Pagefind)
  • Content Collections with type safety
  • Tailwind CSS 4.x styling system
  • View Transitions API for page transitions

Tech Stack Differences

AspectHexo + Shokaastro-koharu
FrameworkHexo (Node.js)Astro 5.x
Template EngineEJS/PugAstro + React
StylingStylusTailwind CSS 4.x
Build ToolWebpackVite
Type CheckingNoneTypeScript
Content MgmtFile systemContent Collections

FAQ

How to Change the Cover Image?

Set the cover field in article frontmatter:

cover: /img/cover/1.webp

Place images in the public/img/ directory. If not set, the default cover will be used.

How to Set a Custom Domain?

After deploying to Vercel, add a custom domain in the Vercel project settings, then update the site.url field in config/site.yaml.

How to Add Comments?

The project supports three comment systems: Waline, Giscus, and Remark42. Choose the provider in the comment configuration block of config/site.yaml. Refer to the Chinese version for detailed configuration of each provider.

How to Preview Draft Articles?

Run pnpm dev in local development mode; drafts will automatically show (with a DRAFT badge).

How to Disable Certain Features?

  • Disable a specific series: Set enabled: false for that series
  • Disable all series: Set featuredSeries to an empty array []
  • Disable search: Remove the pagefind() integration from astro.config.mjs
  • Disable analytics: Set analytics.umami.enabled = false
  • Disable comments: Remove the comment.provider configuration or set it to empty
  • Disable Shoka syntax: Set the corresponding feature to false in the content section of config/site.yaml
  • Disable math formulas: Set content.enableMath = false
  • Disable quizzes: Set content.enableQuiz = false

How to Change Article URL Format?

By default, the filename is used as the URL. You can customize it via the link field:

link: my-custom-url

Reference Resources

Changelog

See CHANGELOG.md for version update history.


If you have questions or suggestions, feel free to submit feedback on GitHub Issues.

喜欢的话,留下你的评论吧~

© 2020 - 2026 cos @cosine
Powered by theme astro-koharu · Inspired by Shoka