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:
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:
localProjectPathmust be an absolute path on your machine; otherwise the correct file path cannot be generatedurlTemplatesupports theplaceholder, 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:
| Field | Required | Description |
|---|---|---|
slug | Yes | URL path, e.g., weekly maps to /weekly |
categoryName | Yes | Category name used to match articles |
label | No | Display label (defaults to categoryName) |
enabled | No | Whether this series is enabled (default true) |
fullName | No | Full name (used for page title) |
description | No | Series description |
cover | No | Cover image path |
icon | No | Navigation icon (Iconify format) |
highlightOnHome | No | Whether to highlight latest article on homepage (default true) |
links | No | Related 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.
Navigation 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 theslugfield configured infeaturedSeries.
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:
categoryMapis only used for URL mapping on category pages (/categories/*). Series page URLs (like/weekly,/reading) are configured separately via theslugfield infeaturedSeries.
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, ormypost, 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.jsonandsimilarities.jsonare 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:
- Have a dedicated series page (URL determined by
slug, e.g.,/weekly,/reading) - Not appear in the regular article list (
/posts) - 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
categoriesfield needs to match thecategoryNameof a series infeaturedSeriesto 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:
| Field | Required | Description |
|---|---|---|
layout | Yes | Fixed to ../layouts/PageLayout.astro |
title | Yes | Page title (for browser tab) |
description | No | Page description (for SEO) |
coverTitle | No | Title displayed on cover (defaults to title) |
comments | No | Whether 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
.mdfiles undersrc/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
Full-Site Search
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: falsefrontmatter 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: falsedisables 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-motionfor 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
| Aspect | Hexo + Shoka | astro-koharu |
|---|---|---|
| Framework | Hexo (Node.js) | Astro 5.x |
| Template Engine | EJS/Pug | Astro + React |
| Styling | Stylus | Tailwind CSS 4.x |
| Build Tool | Webpack | Vite |
| Type Checking | None | TypeScript |
| Content Mgmt | File system | Content 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: falsefor that series - Disable all series: Set
featuredSeriesto an empty array[] - Disable search: Remove the
pagefind()integration fromastro.config.mjs - Disable analytics: Set
analytics.umami.enabled = false - Disable comments: Remove the
comment.providerconfiguration or set it to empty - Disable Shoka syntax: Set the corresponding feature to
falsein thecontentsection ofconfig/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
- Astro Official Documentation
- Tailwind CSS Documentation
- Motion Documentation
- Pagefind Documentation
- Shoka Theme Documentation
Changelog
See CHANGELOG.md for version update history.
If you have questions or suggestions, feel free to submit feedback on GitHub Issues.
喜欢的话,留下你的评论吧~