Oink 0.6.0 — Immersive blogs, safer builds, smaller internals
Oink 0.6.0 keeps the component API established in 0.5 and improves the systems around it: long-form reading, Blog discovery, attribution, release publishing, build resilience, and maintainability.
There is no new article type or second shell. Immersive reading is a
configuration of the existing Blog shell, so articles remain in the same lists,
feeds, taxonomies, series, and pager sequence.
At a glance
- The Blog shell gains a full-bleed
heroimage and an in-flow outline rail. - Blog publishing gains profiles and bylines, series order, list/cards/table indexes, and a local-first share bar.
- Vendored and translated pages gain optional, validated attribution.
- The theme no longer calls
errorf: ordinary previews warn and safely degrade; publishing builds remain strict through--panicOnWarning. - Release metadata is now one
release_url, not a duplicated fact map. - Repeated template work, page bundles, and checker builds have been reduced without pruning Font Awesome or other public authoring assets.
Immersive Blog presentation
An immersive page uses four independent front matter keys:
Put the same keys in a section cascade to apply them to its posts. A section index that should share the presentation also declares them on its own page, because a cascade does not affect the page that owns it.
hero paints the resolved featured image behind the opening and masks it out
before the article text. The ordinary navbar remains available and uses a
fading scrim over the artwork. toc_style: flow gives the outline a wider
in-flow rail that begins with the article and becomes sticky on scroll.
toc_taxonomies: false removes term clouds from that rail.
The Blog shell omits breadcrumbs by default; breadcrumb: true restores one
for a page or cascade that wants it.
Each switch is independent. A missing image produces the normal opening; an empty TOC and disabled clouds produce no empty rail. Nothing changes the page’s Blog membership or output formats.
The Blog, completed
Featured images
params.ui.featured_image and the page key featured_image support:
| Mode | Presentation |
|---|---|
none |
No article image; the default |
banner |
A framed 16:9 image above the title |
wash |
A low-opacity image behind the article header |
hero |
A full-bleed Blog backdrop |
All modes reuse the representative-image resolver also used by list thumbnails and social metadata. Missing images are valid, and non-HTML outputs keep their static source-shaped forms.
Authors
Declare taxonomies: {author: authors}. The author term page is the profile:
its title is the name, its description and body are the biography, and its
representative image is the portrait. Posts list authors with
authors: [vonng, oink]; the order is preserved. The legacy author:
string remains the fallback when the taxonomy is not used.
Series
Declare taxonomies: {series: series}. Posts name one or more terms with
series and may set series_weight. Weighted members come first in
ascending order; unweighted members follow by ascending date. The article and
term page share that resolver, so the position strip and archive cannot drift.
Three index forms
| Key | Default | Meaning |
|---|---|---|
ui.blog_index |
list |
list, cards, or table |
ui.blog_index_columns |
3 |
Card columns |
ui.blog_index_size |
12 |
Posts per list/cards page |
ui.blog_index_toggle |
false |
Reader-side cycle among all three forms |
List and cards share year grouping and pagination. A standalone table is a complete unpaginated archive. With the reader toggle enabled, all three forms share the current paginator slice; the full archive is not repeated on every generated page. The configured form controls first paint, and a local preference may override it.
Sharing
params.ui.share is an ordered list drawn from x, bluesky,
mastodon, facebook, linkedin, reddit, hackernews,
telegram, whatsapp, line, pinterest, weibo, chatgpt,
claude, email, and copy. Empty is the default; share: false
opts out one page.
The bar uses plain intent links and the local copy action. It loads no platform SDK, iframe, counter, or third-party stylesheet.
Page annotation
upstream_link is the per-page source URL. Its companion facts are
upstream_name, upstream_copyright, upstream_license,
upstream_notice, upstream_ref, and upstream_modified. Constants may
come from site parameters, a data/upstreams entry, or front matter.
Incomplete facts, unknown licences, unsafe URLs, and invalid types warn and
omit the whole attribution line. Strict builds reject the warning.
upstream_link: "" explicitly opts a page out of an inherited attribution.
params.ui.translation_notice optionally names the authoritative language.
It is never imposed as page front matter; a page may opt out with
translation_notice: false.
Warnings instead of preview outages
The theme contains no errorf calls. Simple scalar values share
validate.html; components retain the checks that understand their own
records and markup.
Invalid input follows one rule:
- warn with the bad value and the safe fallback or omission;
- do not emit unsafe or misleading output;
- let an ordinary
hugo servercontinue; - let
--panicOnWarningstop CI and publication.
This preserves strict gates without letting one typo take every preview URL down.
Outline rail
The outline exposes a visible range and a current cursor on one SVG path. The
cursor carries aria-current="location"; reduced-motion and unsupported
registered-property engines fall back without detaching the cursor from the
line.
Fixed and simplified
- Mounted content no longer publishes build-machine paths in Edit, History, or Create Child URLs.
- Generic
data-*andaria-*values use one HTML-escaping emitter. - Incomplete Algolia credentials emit no container, CSS, or JavaScript.
- Draw.io loads only on pages with PNG/SVG candidates and inspects each distinct URL once.
- Page actions, pager state, language targets, and section-index children reuse page- or site-scoped results instead of repeating full-site work.
- Language-neutral feature bundles are shared across translations.
- Field anchors are derived from field names and remain unique within a page.
- Print aggregates namespace headings and footnotes without changing regular page IDs.
- The maintained invalid-input checker batches equivalent cases: the content primitive stage now starts Hugo six times instead of 160 while preserving every warning and fallback assertion.
- Obsolete CSS, i18n keys, rejected Article-shell artifacts, duplicate checker blocks, and narrative code comments have been removed. The complete supported Font Awesome distribution remains intact.
Configuration
| Key | Default | Notes |
|---|---|---|
ui.featured_image |
none |
none / banner / wash / hero |
ui.toc_style |
fixed |
fixed / flow |
ui.toc_taxonomies |
true |
Show taxonomy clouds in the right rail |
ui.blog_index |
list |
list / cards / table |
ui.blog_index_columns |
3 |
Card columns |
ui.blog_index_size |
12 |
List/cards page size |
ui.blog_index_toggle |
false |
Reader-side three-form cycle |
ui.share |
[] |
Ordered share targets |
ui.translation_notice |
false |
Optional authoritative language |
time_format_blog |
2006-01-02 |
Changed default |
time_format_default |
2006-01-02 |
Changed default |
The default shell and pager type lists remain docs, book, blog, and
swagger where applicable. No article type is added.
Migration
From 0.5:
- Keep explicit prose date formats if ISO dates are not desired.
- Ensure publishing commands use
--panicOnWarning. - Replace the old
releasemap withrelease_url: https://github.com/<owner>/<repo>/releases/tag/<tag>. - Replace
upstream_attributionwithupstream_link, anddownstream_modifiedwithupstream_modified. - Do not migrate content to
type: article; use the Blog presentation keys shown above.
The migration tool operates on content Markdown and supported YAML front matter.
Configuration-file mappings remain an explicit maintainer task. From 0.4, keep
the established sequence: report, migrate --write, then check.
Verification
The 0.6.0 release is verified with:
- Hugo Extended 0.160.1 and 0.164.0;
- 40 HTML/print/Markdown/RSS/LLMS golden surfaces;
- 85 migration tests and 38 browser-runtime tests;
- strict example, Hugo Module, system-font, legacy-font, and invalid-config builds;
- the bilingual project-site build and its non-browser regression suite;
- representative large-site performance measurement and real EN/ZH browser checks.
Local validation, a commit, a tag, a push, a consumer pin, and deployment remain separate release states.
