halo-theme-dev

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Halo Theme Development

Halo主题开发

Halo is built on Spring Boot + Spring WebFlux + Thymeleaf. Themes use Thymeleaf templates for frontend page rendering.
Halo 基于Spring Boot + Spring WebFlux + Thymeleaf构建。主题使用Thymeleaf模板进行前端页面渲染。

Thymeleaf Quick Reference

Thymeleaf快速参考

Core syntax cheatsheet:
html
<!-- Output text -->
<h1 th:text="${site.title}"></h1>

<!-- Output unescaped HTML -->
<div th:utext="${post.content.content}"></div>

<!-- Links -->
<a th:href="@{${post.status.permalink}}">Post link</a>
<link rel="stylesheet" th:href="@{/assets/dist/style.css}" />

<!-- Loop -->
<li th:each="post : ${posts.items}" th:text="${post.spec.title}"></li>

<!-- Conditionals -->
<div th:if="${posts.hasNext()}">Next page</div>
<div th:unless="${posts.hasNext()}">Last page</div>

<!-- Local variable -->
<div th:with="menu = ${menuFinder.getPrimary()}">...</div>

<!-- Fragment include -->
<div th:replace="~{fragments/header :: header}"></div>

<!-- Layout reuse: layout.html declares a parameterized fragment; pages pass head/content via th:replace -->
<!-- templates/layout.html -->
<html th:fragment="html (head, content)">
  <head>
    <th:block th:if="${head != null}" th:replace="${head}" />
  </head>
  <body>
    <th:block th:replace="${content}" />
  </body>
</html>
<!-- templates/index.html -->
<html th:replace="~{layout :: html(head = null, content = ~{::content})}">
  <th:block th:fragment="content"><!-- page body --></th:block>
</html>

<!-- Inline JavaScript -->
<script th:inline="javascript">
  var url = '[(${#theme.assets("/dist/main.iife.js")})]';
</script>
核心语法速查表:
html
<!-- Output text -->
<h1 th:text="${site.title}"></h1>

<!-- Output unescaped HTML -->
<div th:utext="${post.content.content}"></div>

<!-- Links -->
<a th:href="@{${post.status.permalink}}">Post link</a>
<link rel="stylesheet" th:href="@{/assets/dist/style.css}" />

<!-- Loop -->
<li th:each="post : ${posts.items}" th:text="${post.spec.title}"></li>

<!-- Conditionals -->
<div th:if="${posts.hasNext()}">Next page</div>
<div th:unless="${posts.hasNext()}">Last page</div>

<!-- Local variable -->
<div th:with="menu = ${menuFinder.getPrimary()}">...</div>

<!-- Fragment include -->
<div th:replace="~{fragments/header :: header}"></div>

<!-- Layout reuse: layout.html declares a parameterized fragment; pages pass head/content via th:replace -->
<!-- templates/layout.html -->
<html th:fragment="html (head, content)">
  <head>
    <th:block th:if="${head != null}" th:replace="${head}" />
  </head>
  <body>
    <th:block th:replace="${content}" />
  </body>
</html>
<!-- templates/index.html -->
<html th:replace="~{layout :: html(head = null, content = ~{::content})}">
  <th:block th:fragment="content"><!-- page body --></th:block>
</html>

<!-- Inline JavaScript -->
<script th:inline="javascript">
  var url = '[(${#theme.assets("/dist/main.iife.js")})]';
</script>

Development Workflow

开发工作流

  1. Create a theme folder under
    themes/
    in the Halo working directory (must match
    metadata.name
    in
    theme.yaml
    )
  2. Write
    theme.yaml
    (required) and
    settings.yaml
    (optional)
  3. Create template files under
    templates/
  4. Install and activate the theme in Console → Theme Management
  5. Visit the frontend to verify
Disable Thymeleaf caching during development: set env var
SPRING_THYMELEAF_CACHE=false
(Docker), or
spring.thymeleaf.cache: false
in config (source mode).
  1. 在Halo工作目录的
    themes/
    下创建主题文件夹(必须与
    theme.yaml
    中的
    metadata.name
    一致)
  2. 编写
    theme.yaml
    (必填)和
    settings.yaml
    (可选)
  3. templates/
    下创建模板文件
  4. 在控制台→主题管理中安装并激活主题
  5. 访问前端页面进行验证
开发期间禁用Thymeleaf缓存:设置环境变量
SPRING_THYMELEAF_CACHE=false
(Docker环境),或在配置文件中设置
spring.thymeleaf.cache: false
(源码运行模式)。

Starter Templates

入门模板

The
assets/
directory provides two ready-to-use theme templates:
  • assets/theme-minimal/
    — Zero-build-tool minimal theme with all 8 template files; ideal for quick prototyping or simple themes
  • assets/theme-vite/
    — Vite project template with
    vite-plugin-halo-theme
    (recommended for new themes); includes partial layout reuse and CSS toolchain
Usage: copy the directory into
themes/
in your Halo working directory, ensure the folder name matches
metadata.name
in
theme.yaml
, then install and activate in Console.
assets/
目录提供了两个可直接使用的主题模板:
  • assets/theme-minimal/
    — 无需构建工具的极简主题,包含全部8个模板文件;适合快速原型开发或简单主题
  • assets/theme-vite/
    — 带有
    vite-plugin-halo-theme
    的Vite项目模板(推荐用于新主题开发);包含部分布局复用和CSS工具链
使用方法:将目录复制到Halo工作目录的
themes/
下,确保文件夹名称与
theme.yaml
中的
metadata.name
一致,然后在控制台中安装并激活。

References Index

参考索引

FileContentWhen to read
references/structure-and-config.mdDirectory structure, theme.yaml fields, settings.yaml form definitionCreating a theme, configuring theme.yaml/settings.yaml
references/vite-plugin.mdvite-plugin-halo-theme integration guide, include/slot template syntax, TailwindCSS integrationSetting up a Vite-based theme (recommended)
references/templates.mdTemplate route mapping, available variables per templateWriting template files
references/global-variables.mdGlobal variables (site, theme, theme.config) and type definitionsAccessing site info or theme setting values
references/finder-apis.mdAll Finder APIs (postFinder, categoryFinder, tagFinder, menuFinder, singlePageFinder, etc.)Querying data from any template
references/static-resources.mdStatic asset reference methods (
@{}
,
#theme.assets()
)
Referencing CSS/JS/images in plain HTML themes
references/template-tags.mdCustom tags (halo:comment extension point, halo:footer injection)Integrating comment plugins, injecting footer code
references/annotations.mdAnnotationSetting for model custom fields,
#annotations
utility for reading metadata in templates
Adding custom fields to menu items/posts/categories and using them in templates
references/packaging.mdPackaging a theme as a ZIP using
@halo-dev/theme-package-cli
Preparing a theme for release or upload
文件内容阅读时机
references/structure-and-config.md目录结构、theme.yaml字段、settings.yaml表单定义创建主题、配置theme.yaml/settings.yaml时
references/vite-plugin.mdvite-plugin-halo-theme集成指南、include/slot模板语法、TailwindCSS集成搭建基于Vite的主题时(推荐)
references/templates.md模板路由映射、各模板可用变量编写模板文件时
references/global-variables.md全局变量(site、theme、theme.config)及类型定义访问站点信息或主题设置值时
references/finder-apis.md所有Finder API(postFinder、categoryFinder、tagFinder、menuFinder、singlePageFinder等)在任意模板中查询数据时
references/static-resources.md静态资源引用方法(
@{}
,
#theme.assets()
在纯HTML主题中引用CSS/JS/图片时
references/template-tags.md自定义标签(halo:comment扩展点、halo:footer注入)集成评论插件、注入页脚代码时
references/annotations.md模型自定义字段的AnnotationSetting、在模板中读取元数据的
#annotations
工具类
为菜单项/文章/分类添加自定义字段并在模板中使用时
references/packaging.md使用
@halo-dev/theme-package-cli
将主题打包为ZIP文件
准备发布或上传主题时