Contribution Guide
Project Structure
Version Compatibility
The main branch currently targets Halo 2.x.
Development Guide
Before you start, make sure your editor supports EditorConfig so formatting stays consistent across the project.
Setting Up the Development Environment
Install pnpm
First, install Node.js, then run:
npm install -g pnpmPreparation Before Development
Clone the Project Source Code and Navigate to the Root Directory
git clone https://github.com/HowieHz/halo-theme-higan-hz && cd halo-theme-higan-hz/Install Project Dependencies
In the project root, install dependencies:
pnpm installDeveloping the Theme
To run the theme in development mode with live updates, execute:
pnpm watchUncompressed style files are generated in tmp/, which makes debugging easier.
Writing Documentation
For documentation development with live preview, run:
pnpm docs:watchBuild production docs to docs/.vitepress/dist with:
pnpm docs:buildPreview the production build with:
pnpm docs:previewAfter Development
Formatting Code
Before committing, format the code first:
pnpm fmtLinting
After formatting, run the following command and make sure there are no errors:
pnpm lintBuilding the Theme
Build the theme with:
pnpm buildCI Checks
CI (GitHub Actions) runs the following checks for PRs. Some checks are triggered manually when needed.
CI Formatting Steps
CI first runs pnpm fmt, including the following formatting steps:
oxfmt: Formatting for JSON, JSONC, YAML, Markdown, CSS, JavaScript, TypeScript, HTML, Vue files
Formatting changes are automatically committed only when the PR branch is in this repository. When the PR branch is in a fork, CI keeps the check failing and uploads
ci-autofix.patchfor contributors to download and apply.
CI Linting Steps
After formatting, CI automatically runs pnpm lint, including the following checks:
oxlint+eslint: Code style and type-aware checks- Scope: JavaScript files, TypeScript files, HTML files (inline
scriptblocks only), and Vue files (including inlinescriptblocks)
- Scope: JavaScript files, TypeScript files, HTML files (inline
stylelint: Stylesheet checks- Scope: CSS files, HTML files (inline
styleblocks only), and Vue files (inlinestyleblocks only) - Note: By default,
**/*.{css,html,vue}does not match dot-prefixed directories, so additional path globs are required.
- Scope: CSS files, HTML files (inline
markdownlint: Documentation style checks- Scope: Markdown files
autocorrect: Automated text corrections- Scope: Supported file formats
tsgo -b: TypeScript type checks- Scope: TypeScript files
vue-tsc -b docs/tsconfig.browser.json: Vue / Markdown type checks for the docs site- Scope: Vue components and VitePress Markdown pages under
docs
- Scope: Vue components and VitePress Markdown pages under
All lint steps run with auto-fix enabled. If fixes are applied, they are automatically committed only when the PR branch is in this repository. When the PR branch is in a fork, CI keeps the check failing and uploads
ci-autofix.patchfor contributors to download and apply.
Versioning and Release Guard
- Auto-fix versioning: PRs labeled
releasealso auto-fixpackage.jsonversionthrough the automatic maintenance workflow (maintain-code.yml) after formatting and linting.
This fix runs only when the PR base is the latest commit on the target branch and CI has write access to the PR branch. It only changespackage.json;
if the base is stale, no version fix is produced and the PR branch must be updated first. If the PR branch is in a fork, CI does not push a commit directly,
but any generated version fix is included inci-autofix.patchfor the contributor to apply and commit. - Release guard checks:
- Verifies that
docs/maintenance/changelog.mdanddocs/en/maintenance/changelog.mdstill contain## [Unreleased](fails if missing). - Verifies that changelog compare-link definitions at the end of
docs/maintenance/changelog.mdanddocs/en/maintenance/changelog.mdare complete and match release headings (fails if missing or mismatched). - Ensures non-release PRs do not manually modify the
versionfield inpackage.json(fails if changed). - Ensures release PRs (with the
releaselabel) update theversionfield inpackage.json(fails if unchanged), use a valid semantic version matching/^\d+\.\d+\.\d+$/(fails if invalid), and match the target version inferred from commit-message semantics within the range from the latest stable tag to the PR's latest commit. - Ensures release PRs (with the
releaselabel) are based on the latest commit of the target branch (fails if stale). - Prevents manual changes to
spec.versionintheme.yamlandi18n-settings/theme.*.yamlin PRs (fails if changed).
- Verifies that
Lighthouse CI
- Checks Lighthouse scores and outputs reports (all scores must be full marks).
- Compares page resource-size differences against the baseline version and outputs reports.
Page Resource Size Diff Check
To run the page resource size diff check for the current PR, add a /audit comment to the PR conversation (only users with write, maintain, or admin access can trigger it).
The check runs against the latest commit in the PR and compares page resource sizes with the latest stable release.
Visual Regression Testing
To run the visual regression check for the current PR, add a /visual comment to the PR conversation (only users with write, maintain, or admin access can trigger it).
Playwright captures screenshots of key pages across desktop, tablet, and mobile viewports using Chromium, Firefox, and WebKit, then compares them against the baseline version with Argos CI.
The current automation generates and uploads only Chromium screenshots for comparison.
Appendix: How to Use the Patch
If the PR branch is in a fork and auto-fixes produce uncommitted changes, copy the patch link from the CI job summary and run the matching commands locally on the PR branch.
Linux / macOS:
curl -L -o ci-autofix.patch "<ci-autofix.patch link>" && git apply ci-autofix.patchWindows PowerShell:
Invoke-WebRequest -Uri "<ci-autofix.patch link>" -OutFile ci-autofix.patch; git apply ci-autofix.patchRelease Flow
Pre-release Checklist
Before releasing, confirm all of the following:
- Every branch or PR intended for the release has already been merged.
- The entries under
## [Unreleased]in bothdocs/maintenance/changelog.mdanddocs/en/maintenance/changelog.mdare complete, the## [Unreleased]heading has not been removed, and compare-link definitions at the end are retained (the release workflow will rebuild this section automatically). - In release PRs (with the
releaselabel), onlypackage.jsonversionshould change. The automatic maintenance workflow (maintain-code.yml) can auto-fix it when the PR base is not stale, and that value becomes the target stable version. - Manually verify that the
requiresfield intheme.yamlandi18n-settings/theme.*.yamlstill matches the target Halo CMS compatibility range.
Stable Release Procedure
Stable releases are published automatically from a labeled PR:
- Create a PR for the release (or use an existing aggregation PR).
- Add the
releaselabel. The automatic maintenance workflow (maintain-code.yml) auto-fixespackage.jsonversionto the target semantic version when the PR base is not stale. - Wait for
check-release-guard.ymlto pass and confirm the target version matches the PR's commit-message semantics. - Merge the PR into
main.
After merge, the bot automatically:
- Promotes content under
## [Unreleased]into a new release section in both changelog files, creates the new stable-release heading, and keeps## [Unreleased]. - Rebuilds compare-link definitions at the end of both changelog files (
[Unreleased]and version links). - Updates
package.jsonversion,theme.yamlspec.version, andi18n-settings/theme.*.yamlspec.version, then pushes the bot commit tomain. - Builds the theme and produces multiple
howiehz-higan-*.zippackages. - Runs
gh attestation verifyto confirm everyhowiehz-higan-*.zippackage was signed by the expected reusable build workflow; publishing continues only after verification passes. - After verification passes, two publishing actions run in parallel:
- Create the GitHub Release. Asset order is determined by GitHub.
- Sync to the Halo App Store by creating a draft release first, publishing it only after all build artifacts upload successfully, while ensuring
howiehz-higan-zh-hans.zipstays first in the release asset list so Halo CMS can prefer the Simplified Chinese package during automatic updates.
- After the GitHub Release is published, dispatches the follow-up event that triggers
generate-page-size-audit-json.yml, which creates the page-size audit PR. That PR includes thedeploy-docslabel and deploys docs automatically after merge.
Nightly Pre-release Procedure
Nightly pre-releases do not require manual version changes or a manually pushed branch.
release-nightly-theme-prerelease.ymlruns automatically every day at 00:00 Asia/Shanghai.- A Nightly pre-release is created only when all of the following are true:
- There are commits within the previous calendar-day window in Asia/Shanghai.
- There are commits after the latest stable or pre-release tag.
- Merge commits and commit subjects starting with
docs(for exampledocs:,docs!:,docs!!:) are excluded.
- The Nightly pre-release version rule is “the version inferred from commit-message semantics in the range from the latest stable tag to the latest commit”, then append
-alpha.yyyyMMddHHmmssSSS. - The workflow creates a temporary local branch in the runner, updates version fields, and builds assets without pushing that branch.
- Before publishing the GitHub pre-release or syncing the Halo App Store, the workflow verifies attestation for every nightly
.zipartifact. - After verification passes, the scheduled nightly run creates only the GitHub pre-release and does not sync to the Halo App Store by default.
To create a Nightly pre-release manually, use workflow_dispatch and set the sync_to_halo_store input to control Halo App Store sync after verification passes; when enabled, App Store sync creates a draft release first and publishes it only after all build artifacts upload successfully. This input defaults to false.
Pull Request Conventions
The following conventions are used to mark or trigger PR automation workflows.
Special Labels
deploy-docs: Automatically deploys the documentation site when merged.release: Triggers the stable release creation process. See the Release Flow section for details.
Special Comments
/audit: Triggers the page resource size diff check, compares the current PR with the latest stable release, and generates a report. Only users withwrite,maintain, oradminaccess can trigger it./visual: Triggers the visual regression check, generates screenshots for the latest PR commit, and uploads them to Argos whenARGOS_TOKENis configured. Only users withwrite,maintain, oradminaccess can trigger it.
How to Add a New Feature with Config Options
Update Form Files
Please update the following configuration form files in sync:
- Simplified Chinese:
settings.yaml - English:
i18n-settings/settings.en.yaml
Update Config Documentation
Please update the following configuration documentation in sync:
- Simplified Chinese:
docs/guide/theme-configuration.md - English:
docs/en/guide/theme-configuration.md
When writing docs, follow the format example at the beginning of the document, and keep the option order consistent with the order in the form files.
Update Changelog
Record your changes in the following changelog files:
- Simplified Chinese:
docs/maintenance/changelog.md - English:
docs/en/maintenance/changelog.md