This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
FixIt is a modern, responsive theme for the Hugo static site generator. Built with Hugo templates, SCSS, UnoCSS, and TypeScript.
- Node.js >= 20
- Hugo Extended >= 0.161.0 (Dart Sass required)
- pnpm
pnpm install # Install dependencies
pnpm dev:demo # Start demo site dev server
pnpm dev:test # Start test site dev server
pnpm dev:docs # Start docs dev server (requires fixit-docs as sibling directory)pnpm build:demo # Build demo site
pnpm build:test # Build test site
pnpm build # Build all sites (demo + test, merged into public/)
pnpm preview # Preview built site (requires build first)pnpm gen:lexers # Regenerate assets/scss/core/maps/_chroma-lexers.scss from Chroma sourcepnpm lint # Run ESLint
pnpm typecheck # Run TypeScript type checkingThere are no unit tests. Verify changes by building pnpm build:demo or pnpm build:test and inspecting the output.
Root package.json is @hugo-fixit/core. pnpm workspaces include apps/* and packages/*:
apps/demo/— Demo site (deployed todemo.fixit.lruihao.cn)apps/test/— Test site for exercising theme featurespackages/shared— Shared utilities (exportsworkspaceRoot,fromRoot,runCommand,capitalize,consola)packages/versioning— Version management (auto-updates version inlayouts/_partials/init/index.htmlduring pre-commit)packages/integration— Post-build: merges demo/test output intopublic/packages/chroma-lexers— Generates Chroma lexer SCSS map from GitHub
Service-class architecture with direct constructor calls:
main.ts— Entry point. Instantiates all modules with direct constructor calls, builds the typedwindow.fixitpublic API facade, and runs the init sequence onDOMContentLoaded.types/— TypeScript type definitions:config.ts—FixItConfigand all config sub-types.ui.ts—FixItPublicAPI, globalwindowaugmentation for third-party libs.third-party.ts— Types for vendored libraries.
core/— Infrastructure layer:event-bus.ts— Typed event bus singleton wrapping DOMCustomEvents. ExportseventBus(module-level singleton) andFixItEventMaptype.tokens.ts— Service interfaces (CoreService,ThemeService,CodeService, etc.) used for module constructor typing.
modules/— Feature modules. Each is a class implementing its service interface. Dependencies are constructor-injected. Private state uses ES6#fields. Modules: charts, code, content, core, encryption, events, menu, misc, search, theme, toc.pagefind.tsis a standalone factory consumed bySearchModule.utils/— Pure utility functions (no side effects, no DOM state). Re-exported fromutils/index.ts.lib/— Third-party library wrappers (aplayer, echarts, file-tree, fixit-decryptor, lightgallery, mapbox, mathjax, mermaid, etc.). All import the sharedeventBussingleton.head/—color-scheme.tsruns synchronously in<head>before body render to prevent flash of wrong theme.pages/— Page-specific scripts (e.g.link.tsfor the link guard redirection page).
Cross-module communication uses the shared eventBus singleton, not direct module imports. The window.fixit facade exposes a typed public API for user custom scripts (custom.ts): theme control, scroll state, mask overlay management, content re-initialization, and the event bus.
_partials/— Reusable template components (organized intoinit/,base/,function/,plugin/,single/,store/)_shortcodes/— 31 custom shortcodes (admonition, aplayer, echarts, file-tree, mermaid, tabs, timeline, etc.)_markup/— 15 render hooks (code blocks, headings, images, links, tables, blockquote alerts, passthrough for math)
Hugo Pipes processes all assets. The key orchestration is in _partials/base/assets.html:
- CSS:
scss/main.scssis the entry point importingcore/,pages/,widgets/,custom. SCSS variables are configured viahugo:vars(user-configurable from[params.appearance]) andhugo:vars/internal(theme system config). UnoCSS utility classes are pre-built toassets/css/unocss.css(viapnpm unocss), loaded before the main SCSS bundle. - JS:
_partials/function/js-build.htmlwrapsjs.Buildwith minify-in-production defaults. Hugo's@paramsinjection passes config values into TypeScript at build time. - Third-party libraries: Stored in
assets/lib/(vendored, not npm-managed). Tracked bylibrarybot.ymland updated weekly by thehugo-fixit/librarybotGitHub Action. Can be overridden via CDN config inassets/data/cdn/jsdelivr.ymlorunpkg.yml.
hugo.toml— Default theme configuration (1700+ lines). Uses_merge = "shallow"to let user configs override without deep merging.theme.toml— Theme metadata
- CSS classes: BEM or semantic naming (
header-desktop,menu-item) - SCSS variables: hyphen-separated, semantic (
$global-font-family) - CSS custom properties: prefixed with
fi-/--fi- - Use CSS variables for theme switching; SCSS variables for colors (no hardcoded values)
- Prefer relative units (rem, em, %) over absolute units
- Keep selector nesting shallow
- Pre-built utility classes generated by
pnpm unocss(config:uno.config.ts) - Use atomic classes for common utilities (
hidden,me-1,text-center, etc.) - Theme colors mapped via
@theme:bg-primary,text-success,text-danger, etc. - Responsive breakpoints:
sm:(>=680px),md:(>=960px),lg:(>=1200px),xl:(>=1440px). Usemax-sm:for xs (<680px) - Wrap SVG elements with
<!-- @unocss-skip-start -->/<!-- @unocss-skip-end -->to avoid false positives fromdattribute values safelistinuno.config.tsfor dynamically generated classes (e.g.,order-*,sm:hidden)
- Use ES6
#private fields — not TypeScriptprivatewith_prefix - One module per file, one service interface per module
- Constructor injection for dependencies — no global state access
- Import the shared
eventBussingleton fromcore/event-bus— do not create new instances - Pure functions only in
utils/— no side effects, no DOM state - Comment style: follow TSDoc conventions
- Variable naming: camelCase (
$footerConfig,$fingerprint) - Translation: use
Tfunction ({{ T "header.switchTheme" }}) - Whitespace: use
{{- -}}trim markers - Use
partialCachedfor expensive partials that don't change per page - Use
.Site.Storefor shared computed values (e.g. fingerprint) - Check
hugo.IsProductionbefore adding analytics or minification - Minimize
idattribute usage — prefer class selectors for styling and JS queries. Reserveidfor:<label for>,aria-controls/aria-labelledby, fragment anchors, or third-party library requirements
Follows Conventional Commits:
<type>(<scope>): <subject>
Types: feat, fix, refactor, chore, docs, perf, style, test, ci, build
Scopes: workflow, archetypes, assets, i18n, layouts, config, or specific directories.
Pre-commit runs: versioning (dev mode), typecheck, lint-staged (eslint --fix on staged files).
Uses @antfu/eslint-config with TypeScript support. Config at eslint.config.ts.