Fixes issues flagged in audit: improve footer spacing, meta tag refinement, code-copy utility robustness, and add security notes to data schemas.
tsuki (月)
A Hugo blog + personal portfolio theme. The homepage is the portfolio — bio, featured projects, recent posts. Posts live at /post/. Vietnamese-first typography, View Transitions on navigation, Pagefind search, Giscus comments.
月 (tsuki): the moon. Quiet, observed, returned to. Companion to
bonsaiin the same naming family.
Status
v0.1.0 — initial release. See CHANGELOG.md.
Features
- Blog — posts, tags, categories, year-grouped archive, paginated post list
- Personal portfolio on the homepage — driven by
data/profile.yaml+data/projects.yaml, no separate/portfoliosection - Search — Pagefind, zero-runtime, indexed at build time
- Comments — Giscus (GitHub Discussions)
- Vietnamese-first — diacritic-safe typography, native vi date formats, ASCII heading IDs
- Dark mode —
prefers-color-scheme+ persistent toggle, no flash of wrong theme - View Transitions API — smooth same-document navigation in supporting browsers
- Table of contents — auto-mounted on long posts, sticky on wide viewports, IntersectionObserver active highlight
- No build step — pure Hugo + browser ES modules. No SCSS, no TypeScript, no bundler in the theme
- Light — CSS ≤ 4 KB gz, JS ≤ 1 KB gz (excluding Pagefind UI)
Quick start
As a git submodule
git submodule add https://github.com/tiennm99/tsuki.git themes/tsuki
Add to your site's hugo.yaml:
theme: tsuki
As a Hugo Module
hugo mod init github.com/<you>/<your-site>
hugo mod get github.com/tiennm99/tsuki
Then add to hugo.yaml:
module:
imports:
- path: github.com/tiennm99/tsuki
Configuration
Add the required keys to your site's hugo.yaml:
theme: tsuki
languageCode: vi
defaultContentLanguage: vi
pagination:
pagerSize: 10
path: page
taxonomies:
category: categories
tag: tags
permalinks:
post: /:year/:month/:day/:contentbasename/
markup:
goldmark:
renderer:
unsafe: true
parser:
autoHeadingIDType: github-ascii
tableOfContents:
startLevel: 2
endLevel: 4
Then drop data/profile.yaml and data/projects.yaml into your site (see docs/data-schemas.md).
Hugo doesn't deep-merge nested config from themes — settings above belong in your site hugo.yaml. The exampleSite/hugo.yaml is a complete working example.
Documentation
docs/config.md— full params referencedocs/data-schemas.md—profile.yaml+projects.yamldocs/customization.md— override layouts, tokens, fontsdocs/migrating-from-stack.md— for users coming fromhugo-theme-stack
Search and comments
Search uses Pagefind, built in CI via npx pagefind --site public after Hugo. Pinned in package.json; bumps via Dependabot. No runtime dependency.
Comments use Giscus. Generate config at giscus.app and add to params.comments.giscus.* to enable. Defaults to off.
Browser support
Modern evergreen browsers. View Transitions and :has() are progressive enhancements; the theme remains functional without them.