Skip to content

Oink 0.6.0 — Immersive blogs, safer builds, smaller internals

Oink 0.6.0 adds an immersive presentation to the existing Blog shell, completes Blog publishing with images, authors, series, three index forms and sharing, and replaces build-stopping template errors with safe warnings.

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 hero image 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:

featured_image: hero
toc_style: flow
toc_taxonomies: false
sidebar_enabled: false

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

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:

  1. warn with the bad value and the safe fallback or omission;
  2. do not emit unsafe or misleading output;
  3. let an ordinary hugo server continue;
  4. let --panicOnWarning stop 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-* and aria-* 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:

  1. Keep explicit prose date formats if ISO dates are not desired.
  2. Ensure publishing commands use --panicOnWarning.
  3. Replace the old release map with release_url: https://github.com/<owner>/<repo>/releases/tag/<tag>.
  4. Replace upstream_attribution with upstream_link, and downstream_modified with upstream_modified.
  5. 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.

Full change set

v0.5.0 to v0.6.0