Faithful port of hugo-PaperMod (MIT © 2020 nanxiaobei and adityatelange — see LICENSE).

PaperMod screenshot

Demohttps://themes.getdune.org/papermod

Tags: dune-theme, blog, minimal, faithful

Install

dune theme:install jsr:@dune/theme-papermod@1.0.3 --activate

Or by hand, in config/site.yaml:

themes:
  - name: papermod
    src: jsr:@dune/theme-papermod@1.0.3

theme:
  name: papermod
  src: jsr:@dune/theme-papermod@1.0.3

The stylesheet is the unmodified upstream CSS bundle (all core/, common/ and includes/ files concatenated in Hugo's bundle order), so the rendered pages match PaperMod pixel-for-pixel. Templates reproduce upstream markup and class names 1:1; Hugo template constructs are mapped to Dune equivalents.

Full deviations-from-upstream detail and a config walkthrough are in the live demo's posts.

Templates

Template Upstream layout Notes
default single.html (plain page) anchored headings
post single.html breadcrumbs, draft hint, meta (date · reading time · words · author), cover, TOC, tags, share buttons
blog list.html + home_info.html post entries, first-entry treatment, covers, summaries, pagination
archives archives.html year/month groups with anchor links
search search.html + fastsearch.js same live-results UX (debounce, ↑/↓/→ keys) backed by Dune's /api/search instead of Fuse.js
error 404.html rendered by core for 404/500; status via page.frontmatter.statusCode

Shortcodes → MDX components

Figure, Collapse, Video, Audio, Ltr, Rtl, InTextImg — usable in .mdx content, markup identical to the upstream shortcodes.

Configuration

Admin-editable (config_schema): default_theme (auto/light/dark), show_reading_time, show_word_count, show_breadcrumbs, show_toc, toc_open, show_share_buttons, show_code_copy_buttons, home_title, home_content, footer_text, language_labels (code/name — see Deviations).

Per-page frontmatter (same names as upstream params): showToc, tocOpen, hideMeta, hideSummary, hideAuthor, disableShare, disableAnchoredHeadings, shareButtons: [x, reddit, …], cover: { image, alt, caption, hidden, hiddenInList, hiddenInSingle }, canonicalURL. Home page: homeInfo: { title, content, social: [{name, url}] } or disableSpecial1stPost: true.

Deviations from upstream

  • Search uses Dune's server-side /api/search (results as you type, same keyboard navigation) instead of a client-side Fuse.js index.
  • Heading ids are generated by the theme (marked doesn't emit them); slugs follow the GitHub convention, so in-page links behave like Hugo's.
  • Cover images render as plain <img> — Hugo's build-time responsive srcset generation has no Dune equivalent yet.
  • Language switcher (header lang-menu, post-meta i18n_list "Translations:" list, hreflang alternates) is driven by Dune's per-page translations prop; it lists only languages the current page actually exists in. Labels default to the language code; set the language_labels: name theme option for native names via Intl.DisplayNames ("Deutsch", "日本語"). A locale string keyed by the language code ("de": "Deutsch") overrides both.
  • Not ported: profile-mode home (index_profile.html), taxonomy terms page (terms.html — Dune templates don't receive a terms list), comments partial, Google/Yandex/Bing verification tags, fingerprinted asset integrity attributes.