Files
tsuki/layouts/_partials/head.html
T
tiennm99 4f17588f19 feat: core layouts and partials (Phase 3)
- baseof.html with named blocks (head_extra, body_class, main, scripts)
- single.html with data-pagefind-body wrapper
- list.html using post-card partial
- home.html placeholder (Phase 4 fills hero/projects/recent-posts)
- 404.html with vi i18n
- _partials: head (full meta + OG + Twitter Card + RSS autodiscovery + theme-flash script), header, nav, footer, meta, post-card, icon
- Sample post fixture in exampleSite to validate render

ci: bump GitHub Actions to Node 24-compatible versions

- actions/checkout v4 → v6
- actions/setup-node v4 → v6, node 20 → 22
- actions/upload-pages-artifact v3 → v5
- actions/deploy-pages v4 → v5
2026-05-07 20:45:31 +07:00

69 lines
2.6 KiB
HTML

{{- $title := cond .IsHome site.Title (printf "%s · %s" .Title site.Title) -}}
{{- $description := .Description | default .Summary | default site.Params.description | default site.Title -}}
{{- $ogImage := .Params.image | default site.Params.profile.avatar -}}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="Hugo {{ hugo.Version }} + tsuki">
<title>{{ $title }}</title>
<meta name="description" content="{{ $description }}">
<link rel="canonical" href="{{ .Permalink }}">
{{/* Theme flash prevention — must run before <body> */}}
<script>
(function () {
try {
var stored = localStorage.getItem('tsuki-theme');
if (stored === 'dark' || stored === 'light') {
document.documentElement.setAttribute('data-theme', stored);
}
} catch (e) {}
})();
</script>
{{/* OpenGraph */}}
<meta property="og:title" content="{{ $title }}">
<meta property="og:description" content="{{ $description }}">
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
<meta property="og:site_name" content="{{ site.Title }}">
{{- with $ogImage }}
<meta property="og:image" content="{{ . | absURL }}">
{{- end }}
{{- if and .IsPage .Date }}
<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
{{- with .Lastmod }}
<meta property="article:modified_time" content="{{ .Format "2006-01-02T15:04:05Z07:00" }}">
{{- end }}
{{- end }}
{{/* Twitter Card */}}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ $title }}">
<meta name="twitter:description" content="{{ $description }}">
{{- with $ogImage }}
<meta name="twitter:image" content="{{ . | absURL }}">
{{- end }}
{{/* RSS autodiscovery */}}
{{- with .OutputFormats.Get "RSS" }}
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }}" href="{{ .Permalink }}">
{{- end }}
{{/* Pagination prev/next for SEO — only on paginated kinds */}}
{{- if or .IsHome (eq .Kind "section") (eq .Kind "taxonomy") (eq .Kind "term") }}
{{- with .Paginator }}
{{- if .HasPrev }}<link rel="prev" href="{{ .Prev.URL }}">{{ end }}
{{- if .HasNext }}<link rel="next" href="{{ .Next.URL }}">{{ end }}
{{- end }}
{{- end }}
{{/* Favicon */}}
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="32x32">
{{/* Theme CSS — placeholder; Phase 6 wires resources.Get */}}
{{/* {{ $css := resources.Get "css/tsuki.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}"> */}}