feat: posts, taxonomies, archive (Phase 5)

- post/list.html paginated section list with post-card
- pagination.html partial (renders only when >1 page)
- _default/taxonomy.html for term lists (/tags/, /categories/) with counts
- taxonomy/term.html for single term pages (paginated posts)
- archives/list.html + archive-group.html: year/month grouped flat list
- exampleSite: 4 new posts across 2025-2026, 2 categories, 4 tags, archive index

Modern Hugo 0.146+ template naming: term.html resolved via taxonomy/
path (Hugo 0.154 lookup ignores _default/term.html).
This commit is contained in:
2026-05-07 21:10:28 +07:00
parent eb6c5c1464
commit c30268759f
15 changed files with 187 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
---
title: "Lưu trữ"
description: "Toàn bộ bài viết theo năm và tháng."
---
@@ -0,0 +1,20 @@
---
title: "Ghi chú về Hugo và static site"
date: 2025-08-15T09:00:00+07:00
draft: false
tags: ["hugo", "viet"]
categories: ["ghi-chu"]
description: "Một vài ghi chú khi quay lại với Hugo sau thời gian dài."
---
Hugo là một static site generator viết bằng Go. Lần này quay lại sau một khoảng dài, có nhiều thứ đã đổi.
## Layout convention mới
Từ phiên bản 0.146, Hugo dùng `_partials`, `_markup`, `_shortcodes` cho các thư mục bên trong `layouts/`. Tên thư mục bắt đầu bằng dấu gạch dưới để tách biệt với các kind/section thông thường.
## Vài điều giữ lại
- Markdown thuần là tài sản lâu dài.
- Build chậm thì không phải Hugo.
- Theme nhẹ thì site nhẹ.
@@ -0,0 +1,12 @@
---
title: "Vài suy nghĩ cuối năm"
date: 2025-12-01T20:30:00+07:00
draft: false
tags: ["viet"]
categories: ["ghi-chu"]
description: "Nhìn lại một năm với nhiều thay đổi nhỏ."
---
Cuối năm là lúc thích hợp để dừng lại. Không phải để tổng kết, mà để quan sát.
Có những thứ năm nay tôi làm tốt hơn năm ngoái. Và có những thứ vẫn vậy. Cả hai đều ổn.
@@ -0,0 +1,20 @@
---
title: "Lập kế hoạch đầu năm"
date: 2026-01-10T08:00:00+07:00
draft: false
tags: ["tsuki", "hugo"]
categories: ["demo"]
description: "Bắt đầu năm mới bằng một kế hoạch nhỏ và một theme mới."
---
Đầu năm tôi thường viết ra ba thứ muốn làm xong trong sáu tháng đầu. Năm nay một trong số đó là viết một theme Hugo riêng — tsuki.
## Vì sao tự viết
Theme đang dùng tốt, nhưng nặng. Có nhiều thứ tôi không cần. Tự viết là cách hiểu rõ từng dòng.
## Mục tiêu
1. Không có bước build cho CSS/JS — chỉ Hugo + ES modules trình duyệt hiểu được.
2. Tiếng Việt trước. Ngôn ngữ khác không phải mục tiêu.
3. Trang chủ là portfolio. Bài viết là phần còn lại.
@@ -0,0 +1,14 @@
---
title: "Đọc sách và quan sát"
date: 2026-03-22T15:00:00+07:00
draft: false
tags: ["viet", "demo"]
categories: ["ghi-chu"]
description: "Đọc chậm hơn, viết ngắn hơn, quan sát kỹ hơn."
---
Tôi đang thử đọc lại những cuốn cũ. Lần trước đọc lướt; lần này đọc kỹ.
Phát hiện ra: phần lớn ấn tượng đầu tiên về một cuốn sách là sai. Không phải vì cuốn sách thay đổi — mà vì tôi đã đọc khác đi.
> Tháng ấy đẹp quá nhỉ.
+4
View File
@@ -0,0 +1,4 @@
---
title: "Bài viết"
description: "Tất cả ghi chú và bài viết."
---
View File
+19
View File
@@ -0,0 +1,19 @@
{{ define "body_class" }}list taxonomy-list{{ end }}
{{ define "main" }}
<header class="list-header">
<h1 class="list-title">{{ .Title }}</h1>
{{- with .Description }}<p class="list-description">{{ . }}</p>{{ end }}
</header>
<ul class="terms-list">
{{- range .Pages.ByTitle }}
<li class="term-item">
<a class="term-link" href="{{ .RelPermalink }}">
<span class="term-name">{{ .Title }}</span>
<span class="term-count" aria-label="{{ len .Pages }} {{ i18n "posts" | default "bài" }}">{{ len .Pages }}</span>
</a>
</li>
{{- end }}
</ul>
{{ end }}
+17
View File
@@ -0,0 +1,17 @@
{{- $year := . -}}
<section class="archive-year">
<h2 class="archive-year-heading">{{ $year.Key }}</h2>
{{- range $year.Pages.GroupByDate "1" }}
<section class="archive-month">
<h3 class="archive-month-heading">{{ i18n "month" (dict "Number" .Key) | default (printf "Tháng %s" .Key) }}</h3>
<ul class="archive-post-list">
{{- range .Pages }}
<li class="archive-post-item">
<time datetime="{{ .Date.Format "2006-01-02" }}" class="archive-post-date">{{ .Date.Format "02/01" }}</time>
<a class="archive-post-link" href="{{ .RelPermalink }}">{{ .Title }}</a>
</li>
{{- end }}
</ul>
</section>
{{- end }}
</section>
+26
View File
@@ -0,0 +1,26 @@
{{- $p := .Paginator -}}
{{- if gt $p.TotalPages 1 -}}
<nav class="pagination" aria-label="Pagination">
{{- if $p.HasPrev }}
<a class="pagination-prev" rel="prev" href="{{ $p.Prev.URL }}"> {{ i18n "prev" | default "Trước" }}</a>
{{- else }}
<span class="pagination-prev disabled" aria-disabled="true"> {{ i18n "prev" | default "Trước" }}</span>
{{- end }}
<ol class="pagination-pages">
{{- range $p.Pagers }}
{{- if eq . $p }}
<li><span class="pagination-current" aria-current="page">{{ .PageNumber }}</span></li>
{{- else }}
<li><a href="{{ .URL }}">{{ .PageNumber }}</a></li>
{{- end }}
{{- end }}
</ol>
{{- if $p.HasNext }}
<a class="pagination-next" rel="next" href="{{ $p.Next.URL }}">{{ i18n "next" | default "Tiếp" }} </a>
{{- else }}
<span class="pagination-next disabled" aria-disabled="true">{{ i18n "next" | default "Tiếp" }} </span>
{{- end }}
</nav>
{{- end -}}
View File
+17
View File
@@ -0,0 +1,17 @@
{{ define "body_class" }}list archive{{ end }}
{{ define "main" }}
<header class="list-header">
<h1 class="list-title">{{ .Title }}</h1>
{{- with .Description }}<p class="list-description">{{ . }}</p>{{ end }}
</header>
<div class="archive">
{{- $posts := where site.RegularPages "Section" "post" }}
{{- range $posts.GroupByDate "2006" }}
{{ partial "archive-group.html" . }}
{{- else }}
<p class="archive-empty">{{ i18n "archiveEmpty" | default "Chưa có bài viết." }}</p>
{{- end }}
</div>
{{ end }}
View File
+16
View File
@@ -0,0 +1,16 @@
{{ define "body_class" }}list section-post{{ end }}
{{ define "main" }}
<header class="list-header">
<h1 class="list-title">{{ .Title }}</h1>
{{- with .Description }}<p class="list-description">{{ . }}</p>{{ end }}
</header>
<div class="post-list">
{{- range .Paginator.Pages }}
{{ partial "post-card.html" . }}
{{- end }}
</div>
{{ partial "pagination.html" . }}
{{ end }}
+18
View File
@@ -0,0 +1,18 @@
{{ define "body_class" }}list term-list{{ end }}
{{ define "main" }}
<header class="list-header">
<h1 class="list-title">
<span class="term-prefix" aria-hidden="true">#</span>{{ .Title }}
</h1>
{{- with .Description }}<p class="list-description">{{ . }}</p>{{ end }}
</header>
<div class="post-list">
{{- range .Paginator.Pages }}
{{ partial "post-card.html" . }}
{{- end }}
</div>
{{ partial "pagination.html" . }}
{{ end }}