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

Demo: https://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 responsivesrcsetgeneration has no Dune equivalent yet. - Language switcher (header
lang-menu, post-metai18n_list"Translations:" list,hreflangalternates) is driven by Dune's per-pagetranslationsprop; it lists only languages the current page actually exists in. Labels default to the language code; set thelanguage_labels: nametheme option for native names viaIntl.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.