mirror of
https://github.com/tiennm99/tsuki.git
synced 2026-05-29 16:25:37 +00:00
10a71228ea
- README: add a11y badge linking to docs/accessibility.md. - CHANGELOG: full v0.3.0 entry under Unreleased (Added/Changed/Fixed/ Deferred-to-v0.3.1). Documents per-kind CSS bundles, Tier A features, Lighthouse-relevant polish, contrast-token visual diff, tap-target sizing decisions, and Hugo CI matrix. - docs/accessibility.md: new — WCAG 2.2 AA conformance summary, Lighthouse measurement instructions, projected baseline (TBD entries to fill after first production deploy), known limitations. - docs/customization.md: cover-image override snippet (v0.4.0 native pipeline promise); document breadcrumbs/prev-next/lang-switcher opt-ins. - plans/260510-0144-tsuki-v0.3.0/: mark all phases completed; note narrow-TOC <details> deferral to v0.3.1; record audit-pass scope additions integrated into Phases 2–6. - plans/reports/: add researcher-260515-tsuki-vs-stack-papermod-feature -gap.md (verdict: feature parity on must-haves; Tier A gaps shipped this round) + code-reviewer-260515-lighthouse-80-baseline-audit.md (projected ≥80 on all 4 categories; ≥95 a11y achievable with shipped fixes).
226 lines
6.6 KiB
Markdown
226 lines
6.6 KiB
Markdown
# Customization
|
||
|
||
Hugo's lookup order means **anything in your site overrides the theme**. No fork required.
|
||
|
||
## Override layouts and partials
|
||
|
||
Drop a file with the same path under your site's `layouts/` to replace the theme version.
|
||
|
||
```
|
||
your-site/
|
||
└── layouts/
|
||
├── _partials/
|
||
│ └── footer.html # overrides themes/tsuki/layouts/_partials/footer.html
|
||
└── single.html # overrides themes/tsuki/layouts/single.html
|
||
```
|
||
|
||
To extend rather than replace, copy the theme partial into your site, then modify. Common overrides:
|
||
|
||
- `_partials/footer.html` — add license, build info, web ring links
|
||
- `_partials/home/hero.html` — restructure the homepage hero
|
||
- `_partials/comments.html` — swap Giscus for a different provider
|
||
|
||
## Override design tokens
|
||
|
||
Tokens are CSS custom properties on `:root` and `:where([data-theme="dark"])`. Override them in a custom stylesheet without editing the theme.
|
||
|
||
```css
|
||
/* your-site/assets/css/custom.css */
|
||
:root {
|
||
--tsuki-accent: #cc7a3b; /* warmer accent */
|
||
--tsuki-font-sans: "Public Sans", system-ui, sans-serif;
|
||
--tsuki-content-width: 48rem; /* wider posts */
|
||
}
|
||
:where([data-theme="dark"]) {
|
||
--tsuki-accent: #f0a070;
|
||
}
|
||
```
|
||
|
||
Append it to the bundle by overriding `_partials/head.html`. Copy the theme version, add your file:
|
||
|
||
```go-html-template
|
||
{{- $cssFiles := slice
|
||
(resources.Get "css/tokens.css")
|
||
(resources.Get "css/reset.css")
|
||
...
|
||
(resources.Get "css/view-transitions.css")
|
||
(resources.Get "css/custom.css") {{/* your override, last in cascade */}}
|
||
-}}
|
||
```
|
||
|
||
## Add custom icons
|
||
|
||
Drop SVGs into `assets/icons/<name>.svg`, then reference by name:
|
||
|
||
```yaml
|
||
# data/profile.yaml
|
||
links:
|
||
- icon: bluesky
|
||
label: Bluesky
|
||
url: https://bsky.app/profile/...
|
||
```
|
||
|
||
Use `currentColor` for fill/stroke so icons inherit text color in light and dark modes:
|
||
|
||
```svg
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||
<path d="..."/>
|
||
</svg>
|
||
```
|
||
|
||
## Self-host fonts
|
||
|
||
The theme stack is `"Inter", "Be Vietnam Pro", system-ui, ...`. The first two fall back to system fonts when missing. To self-host:
|
||
|
||
1. Subset Be Vietnam Pro + Inter to `vietnamese,latin` ranges.
|
||
2. Drop the woff2 files into `static/fonts/`.
|
||
3. Add `@font-face` declarations in `assets/css/custom.css` (see "Override design tokens" above).
|
||
|
||
```css
|
||
@font-face {
|
||
font-family: "Inter";
|
||
src: url("/fonts/Inter-VariableFont_slnt,wght.woff2") format("woff2-variations");
|
||
font-weight: 100 900;
|
||
font-display: swap;
|
||
}
|
||
@font-face {
|
||
font-family: "Be Vietnam Pro";
|
||
src: url("/fonts/BeVietnamPro-Regular.woff2") format("woff2");
|
||
font-weight: 400;
|
||
font-display: swap;
|
||
}
|
||
```
|
||
|
||
## Override colors per-page
|
||
|
||
Set CSS variables inline via a frontmatter `style` you wire up yourself, or use the `body_class` block from `baseof.html`:
|
||
|
||
```html
|
||
<!-- layouts/section/work.html -->
|
||
{{ define "body_class" }}list section-work{{ end }}
|
||
```
|
||
|
||
Then style `body.section-work { --tsuki-accent: #...; }` in your custom CSS.
|
||
|
||
## Callouts (admonitions)
|
||
|
||
Use Hugo's native Markdown alert syntax (Hugo 0.140+) — no shortcode needed:
|
||
|
||
```markdown
|
||
> [!note]
|
||
> Useful side information.
|
||
|
||
> [!tip]
|
||
> Reader-friendly hint.
|
||
|
||
> [!important]
|
||
> Hard requirement.
|
||
|
||
> [!warning]
|
||
> Heads-up about a pitfall.
|
||
|
||
> [!caution]
|
||
> Risk of breakage.
|
||
```
|
||
|
||
Titles localize via `i18n/vi.yml` keys `calloutNote`, `calloutTip`, `calloutImportant`, `calloutWarning`, `calloutCaution`. Override per-callout with `> [!note] Custom title`.
|
||
|
||
Plain `> blockquote` still renders as the regular muted blockquote — only `[!type]` triggers callout styling.
|
||
|
||
**Override callout colors** in your custom CSS — each callout type exposes the `--tsuki-callout` and `--tsuki-callout-bg` tokens through its modifier class:
|
||
|
||
```css
|
||
/* your-site/assets/css/custom.css */
|
||
.callout-note { --tsuki-callout: #ff5d8f; --tsuki-callout-bg: #ff5d8f1f; }
|
||
```
|
||
|
||
## Show word count
|
||
|
||
Reading time is shown on every post by default. Add word count under it with:
|
||
|
||
```yaml
|
||
params:
|
||
showWordCount: true # default false
|
||
```
|
||
|
||
The byline reads `5 phút đọc · 1024 từ` (translated via the `wordCount` i18n key).
|
||
|
||
## Accessibility & SEO defaults
|
||
|
||
The theme includes accessibility features that require no configuration:
|
||
|
||
- **Skip-link** — first focusable element on every page; jumps to `<main id="main">` (WCAG 2.1 M3)
|
||
- **Focus rings** — visible outline via `--tsuki-accent` on `:focus-visible` for keyboard navigation
|
||
- **Lastmod byline** — shows "Cập nhật {date}" when modified date is ≥24h newer than publish date
|
||
- **Lazy-load images** — all in-content images get `loading="lazy" decoding="async"` via render hook
|
||
- **External link security** — all Markdown links to `http://` / `https://` / `//` get `rel="noopener noreferrer"` automatically
|
||
|
||
All of these are transparent — no override hooks needed unless you want to customize the markup.
|
||
|
||
## Disable features
|
||
|
||
Every interactive feature has a kill switch:
|
||
|
||
```yaml
|
||
params:
|
||
search:
|
||
enable: false # removes search button + /search/ route
|
||
comments:
|
||
giscus:
|
||
enable: false # comments partial becomes a no-op
|
||
```
|
||
|
||
Per-post:
|
||
```yaml
|
||
toc: false
|
||
comments: false
|
||
```
|
||
|
||
## Cover images
|
||
|
||
`cover.image` is currently used for OG / Twitter card metadata only — the theme does **not** render a hero cover above the post title by default. This avoids LCP regressions on themes with un-optimised consumer-supplied images.
|
||
|
||
To render a cover, override `layouts/single.html` in your site:
|
||
|
||
```hugo
|
||
{{ define "main" }}
|
||
{{ partial "breadcrumbs.html" . }}
|
||
|
||
<article class="post">
|
||
<header class="post-header">
|
||
{{- with .Params.cover.image }}
|
||
{{- /* Use Hugo image processing for a responsive, hashed asset */ -}}
|
||
{{- $img := resources.Get . | images.Resize "1200x" -}}
|
||
<img class="post-cover"
|
||
src="{{ $img.RelPermalink }}"
|
||
width="{{ $img.Width }}" height="{{ $img.Height }}"
|
||
alt="" fetchpriority="high" decoding="async">
|
||
{{- end }}
|
||
<h1 class="post-title">{{ .Title }}</h1>
|
||
{{ partial "meta.html" . }}
|
||
</header>
|
||
<div class="post-content" data-pagefind-body>{{ .Content }}</div>
|
||
</article>
|
||
|
||
{{ partial "prev-next.html" . }}
|
||
{{ partial "related-posts.html" . }}
|
||
{{ partial "comments.html" . }}
|
||
{{ end }}
|
||
```
|
||
|
||
A built-in cover pipeline with `srcset`/AVIF is planned for **v0.4.0**.
|
||
|
||
## Breadcrumbs, prev/next, language switcher
|
||
|
||
These ship in v0.3.0 as opt-in features.
|
||
|
||
```yaml
|
||
params:
|
||
breadcrumbs:
|
||
enable: true # Home › Section › Page trail + BreadcrumbList JSON-LD
|
||
prevNextNav:
|
||
enable: true # in-section prev/next post nav below content
|
||
```
|
||
|
||
The language switcher partial auto-emits when `hugo.IsMultilingual` is true; no config flag needed.
|