Loading...

Loading...

Post Page Configuration

This page explains the post page configuration: hero image, meta info under the title (date/word count/reading time/views), TOC, comments, reward, copyright, math and diagrams. Everything lives in the post section of the theme config.

The authoritative source of the theme config is userConfig/_config.tmp.yml (it overwrites the theme config at CI time).

Display & Layout

1. Post Page Hero Image

Purpose: the banner at the top of post pages (distinct from the homepage hero; set independently).

Config (theme config, post section):

post:
  banner_img: /img/default.png   # post page hero image
  banner_img_height: 70          # hero image height (percentage of screen, 0-100)
  banner_mask_alpha: 0.3         # black mask opacity (0-1)

A single post can override the global setting with banner_img in front-matter.

Hero image source priority (_partial/post/post-cover rendering logic):

  1. front-matter img (e.g. img: /medias_webp/xxx.webp) — explicit
  2. without img, pick one from theme.featureImages by a hash of the title (/medias_webp/featureimages/0-44.webp; the same title always gets the same image)
  3. when random background is on (theme.background.image.random), the post banner is hidden

Note: featureImages only sources from medias_webp/featureimages/ (webp, numbered 0-44, with a dark/ subdirectory); the legacy medias/featureimages/ (jpg) is removed — do not reference .jpg paths.

2. Meta (meta)

Purpose: the info row under the post title: date, word count, reading time, views — each independently toggleable.

Config (theme config, post.meta section):

post:
  meta:
    author:                 # author (front-matter author first, then site author)
      enable: false
    date:                   # post date (front-matter date first, then md file date)
      enable: true
      format: "LL a"        # ISO-8601 date format
    wordcount:              # word count
      enable: true
    min2read:               # reading time estimate
      enable: true
      awl: 1                # average word length (chars per word): 1 for CJK-dominant sites
      wpm: 300              # words per minute: 250-350 recommended for CJK technical content
    views:                  # view counter
      enable: true
      source: "umami"       # data source: busuanzi | leancloud | umami | waline

Notes: post.meta.views.source decides where views come from — this blog uses umami (self-hosted analytics); alternatives include busuanzi (zero config) or Waline comment views.

3. Updated Notice (updated)

Purpose: show “last updated on X” at the top of the post; defaults to the md file modification time, overridable with updated in front-matter.

Config (theme config):

post:
  updated:
    enable: false             # off by default
    date_format: "LL a"       # ISO-8601 format
    relative: false           # true = relative time ("3 days ago")
    note_class: info          # notice style: default | primary | info | success | warning | danger | light

4. TOC

Purpose: chapter navigation in the post sidebar, current chapter highlighted while scrolling, collapsible.

Config (theme config, top-level toc section):

toc:
  enable: true                        # global switch
  headingSelector: "h2,h3,h4,h5,h6"   # heading levels included
  collapseDepth: 0                    # collapse depth (0 all collapsed, >0 expands when children exist)

Disable for a single post: add toc: false in front-matter.

5. Comments (comments)

Purpose: site-wide comment system switch and engine selection.

Config (theme config, post.comments section):

post:
  comments:
    enable: true
    type: waline    # engines: utterances | disqus | gitalk | gitment | valine | waline | changyan | livere | remark42 | twikoo | cusdis | giscus | discuss

Notes: whichever engine type points to, you must also configure that plugin’s required params (e.g. this blog’s waline.serverURL, see the Layout & Pages chapter). Page-level control uses front-matter comments: true/false (same for standalone pages, message pages and friends pages).

5.1 Comment Engine Configs

Waline (this blog’s primary, detailed):

waline:
  enable: true
  serverURL: 'https://waline.17lai.site'   # Waline service address (self-hosted, required)
  avatar: 'mp'          # avatar style: ''/mp/identicon/monsterid/wavatar/retro/hide
  lang: zh-CN           # UI language
  dark: 'html[data-user-color-scheme="dark"]'  # dark mode selector
  login: enable         # login mode: enable | force
  wordLimit: 1000       # comment word limit (0 = unlimited)
  pageSize: 10          # comments per page
  pageview: false       # post page views v2 (with post.meta.views.source: waline)
  comment: true         # comment count v2 (with postInfo.commentCount)
  reaction: |           # post reactions (custom emoji URL array, matching _config.tmp.yml)
    [
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_agree.png',
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_look_down.png',
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_sunglasses.png',
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_pick_nose.png',
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_awkward.png',
      'https://testingcf.jsdelivr.net/npm/@waline/emojis/tieba/tieba_sleep.png'
    ]
  search: false         # emoji search (default provided by giphy)
  imageUploader: false  # image upload (false disables; default embeds as Base64)
  meta: "['nick', 'mail', 'link']"   # fields guests can fill
  requiredMeta: "['nick', 'mail']"   # required fields
  recaptchaV3Key: ''    # reCAPTCHA v3 key (anti-spam, optional)
  highlight:
    enable: false            # disable Waline's built-in highlighter
    custom_highlighter: |    # custom highlight function (waline.ejs reads highlight.custom_highlighter)
      (code, lang) => { /* highlight with Prism */ }

These are the keys actually read by waline.ejs (serverURL/avatar/lang/dark/login/wordLimit/pageSize/pageview/comment/reaction/search/imageUploader/meta/requiredMeta/recaptchaV3Key/highlight.custom_highlighter). Valine-specific keys (enableQQ/recordIP/requiredFields/guest_info/count/visitor) are not read by waline.ejs — configuring them has no effect.

Other engines (condensed config):

EngineConfig keyRequired paramsNotes
ValinevalineappId/appKey/serverURLs (Valine-specific keys enableQQ/recordIP/requiredFields/guest_info/count/visitor)legacy comments (Waline’s predecessor), params same as Waline, needs LeanCloud credentials; prefer Waline
Gitalkgitalkowner/repo/oauth.clientId/oauth.clientSecret/adminGitHub Issues-based; OAuth app has excessive permissions, not recommended
Gitmentgitmentowner/repo/oauth.clientId/oauth.clientSecretGitHub Issues-based; same security issue as Gitalk (see §13)
Disqusdisqusshortnamemainstream foreign comment service, unstable in China
LiverelivereuidKorean service, works in China
ChangyanchangyanappId/confSohu service, requires ICP filing
TwikootwikooenvId (optional region/path)Tencent CloudBase deployment, see twikoo.js.org
Cusdiscusdishost/app_id/langthird-party or self-hosted, see cusdis.com
Giscusgiscusrepo/repo-id/category/category-id (optional mapping/theme-light/theme-dark/lang)GitHub Discussions-based, see giscus.app
Remark42remark42host/site_id (optional max_shown_comments/locale/components)requires self-hosted server, see remark42.com
DiscussdiscussserverURLs/pathself-hosted, multi-platform multi-database, see discuss.js.org
Utterancesutterancesrepo/label (optional issue_term/theme/theme_dark)lightweight GitHub Issues-based comments, needs a GitHub repo, see utteranc.es

Switching engines in three steps: ① set post.comments.type to the target engine; ② fill in the required params from the table above; ③ hexo clean && hexo generate to rebuild. GitHub-based engines (Gitalk/Gitment) carry OAuth permission risks — prefer utterances/giscus-style single-repo solutions.

6. Reward (reward)

Purpose: a tipping card at the end of posts showing WeChat/Alipay payment QR codes.

Config (theme config):

post:
  reward:
    enable: true
    title: 码字辛苦,打赏作者!
    wechat: /medias_webp/reward/wechat.webp   # WeChat payment QR image
    alipay: /medias_webp/reward/alipay.webp   # Alipay payment QR image

Notes: replace the QR images with your own; full URLs for network images are supported.

Purpose: copyright card at the bottom of posts: author, original link and reprint license.

Config (theme config):

post:
  copyright:
    enable: true           # show copyright notice
    license: 'cc_by_nc_sa' # default reprint rule (sub-key of copyright, site-wide)

Per-post front-matter override:

reprintPolicy: cc_by_nc   # this post: Attribution-NonCommercial

Available rules: cc_by, cc_by_nd, cc_by_sa, cc_by_nc, cc_by_nc_nd, cc_by_nc_sa (meanings at Creative Commons).

Content Rendering

8. Math (math)

Purpose: render $...$ / $$...$$ formulas in posts.

Config (theme config):

post:
  math:
    enable: false           # posts use it by default when enabled
    specific: true          # true = only posts with mathjax: true in front-matter load it (saves bandwidth)
    engine: mathjax         # engine: mathjax | katex

Notes: specific: true is this blog’s recommended usage — posts without formulas don’t load the engine; when needed, add mathjax: true in front-matter (markdown-plugins.ejs checks page.mathjax). Custom pages (non-post) using formulas also need mathjax: true in front-matter.

9. Diagrams (mermaid)

Purpose: render mermaid flowcharts/sequence diagrams/gantt charts in posts (```mermaid code blocks or the tag plugin).

Config (theme config):

post:
  mermaid:
    enable: true            # posts use it by default when enabled
    specific: true          # true = only posts with mermaid: true in front-matter load it
    options:                # mermaidAPI config
      theme: 'default'      # theme (dynamically overridden by light/dark mode)
      startOnLoad: true
      securityLevel: 'loose'
      flowchart:
        useMaxWidth: false  # don't stretch to container width in flowcharts
      gantt:
        useMaxWidth: true
        barHeight: 20
        barGap: 4

Notes: the mermaid library is slow to load; with specific: true, write mermaid: true in front-matter to enable it (the same on-demand loading pattern as math). theme is dynamically overridden by light/dark mode but serves as the default.

10. Other Post Page Features

The post section also includes (see the Layout & Pages chapter):

post:
  prev_next:
    enable: true        # prev/next navigation cards
  outdate:              # outdated content notice (off by default)
    enable: false
    warning_day: 365
    error_day: 3650
  category_bar:         # show posts of the current category in the sidebar
    enable: true
    specific: true      # true = only shows with category_bar: true in front-matter
    post_order_by: '-date'  # example: date desc (theme default config sorts by title)
    post_limit: 0       # max items shown (0 = unlimited)
  webpush:              # browser push subscription button (webpushr)
    enable: true
  advertisements:       # sidebar ad cards (array, individually toggleable)
    - id: "ad-1"
      text: "Ad copy"
      enable: true

Browser push subscription (webpush): with post.webpush.enable: true, the post detail page shows a webpushr subscribe button at the bottom (_partial/common/webpush); readers who allow it receive browser push notifications when new posts are published. Register your site at app.webpushr.com and inject the subscription script (the webpushr site ID lives in the theme head template).

Info Display

11. Post Info (postInfo)

Purpose: independent switches for the post info bar — author, date, word count, total count, reading time, reading mode, read count, comment count. This is a separate mechanism from §2 post.meta.

Config (theme config):

postInfo:
  author: true        # author
  date: true          # publish date
  update: true        # update date
  wordCount: true     # post word count
  totalCount: true    # site total word count
> `totalCount` (`totalcount(site)`) covers **posts + wiki pages**: **deduplicated across language versions** (same content counted once) and **encrypted posts counted by plaintext**.
  min2read: true      # reading time
  readMode: true      # reading mode
  readCount: true     # read count
  commentCount: true  # comment count (currently supports waline)

Notes: Word count and reading time are provided by the theme’s built-in helpers (scripts/helpers/wordcount.js) — no extra plugin is required. The wordcount / min2read / totalcount helpers are theme-native; totalcount renders the site-wide total in the footer (including wiki pages and the plaintext count of encrypted posts).

12. Decorative HR (hr)

Purpose: beautified horizontal rule for --- dividers in posts.

Config (theme config):

hr:
  enable: false   # false | true

Notes: when enabled, Markdown --- renders as a decorated divider instead of a plain thin line.

Stats & Verification

13. Gitment Comments (gitment)

Purpose: GitHub Issues-based comment system (Gitment). Disabled by default — this blog primarily uses Waline.

Config (theme config):

gitment:
  enable: false
  owner:            # GitHub username
  repo:             # repo that stores comments
  oauth:
    clientId:       # GitHub OAuth App Client ID
    clientSecret:   # GitHub OAuth App Client Secret

Notes: requires creating a GitHub OAuth App and filling owner/repo/clientId/clientSecret. Security warning: Gitment/Gitalk-style OAuth apps have excessive permissions (can read/write all of the authorizer’s public repos) — an attacker with the Token can wipe your public repos. Prefer utterances-style GitHub Apps scoped to a single repo (see config comments).

14. Tencent Captcha (tcaptcha)

Purpose: Tencent captcha (slider/click) before comment submission, to block spam.

Config (theme config):

tcaptcha:
  enable: false
  appid: 2057160203   # your appid

Notes: currently only adapted and tested with Valine — other comment systems are unverified. Create a captcha in the Tencent Cloud Captcha console to get an appid; intro: official docs.

15. Waline Site Counter (minWalineCount)

Purpose: footer site-wide PV (page views) counter, served by Waline.

Config (theme config):

minWalineCount:
  enable: true
  serverURL: 'https://waline.17lai.site'
  pageview: true   # page view stats v2

Notes: the footer “site PV” is fetched and updated from the Waline service by walineCount.ejs.

16. Waline Comment Counter (minWalineCommentCount)

Purpose: site-wide comment count statistics.

Config (theme config):

minWalineCommentCount:
  enable: false
  serverURL: 'https://waline.17lai.site'
  comment: true   # comment count stats v2

Notes: disabled by default — comment counts are already handled by waline.ejs (theme.waline.comment); enabling this would duplicate requests.

17. Post Password Verification (verifyPassword)

Purpose: set an access password for specific posts; readers must enter it to read.

Config (theme config):

verifyPassword:
  enable: false
  promptMessage: 请输入访问本文章的密码
  errorMessage: 密码错误,将返回主页!

Post front-matter (in-house HBE v4 since 2026-08-09; the password is plaintext, a SHA256 hash is no longer required):

password: "your password"      # plaintext password

Notes: in-house HBE v4 (AES-256-GCM, replacing hexo-blog-encrypt since 2026-08-09) — server-side AES-256-GCM encryption stores ciphertext in HTML (no plaintext leakage), front-end WebCrypto decryption. Write the plaintext password directly in front-matter password (no SHA256 pre-hashing needed).

Other encryption methods:

  • Content snippet encryption: {% encrypt password "title" "abstract" %}...{% endencrypt %} (paragraph-level, supports nested tags, see Tag Plugins §15)
  • Wiki-wide encryption: add encrypt_password to {wiki}-sidebar.yml (see Layout & Pages §8)
  • Password storage: autoSave stores the derived DK (not the plaintext password), 1-day TTL

See the Layout & Pages chapter for full configuration.

Sharing & Recommendations

18. Post Sharing (sharejs)

Purpose: share buttons at the bottom of posts, supporting multiple platforms.

Config (theme config):

sharejs:
  enable: true
  sites: twitter,facebook,qq,qzone,wechat,weibo,douban

Notes: sites is a comma-separated list; options: twitter, facebook, google, qq, qzone, wechat, weibo, douban, linkedin.

19. AddThis Sharing (addthis)

Purpose: AddThis-based sharing module (alternative to sharejs).

Config (theme config):

addthis:
  enable: false
  pubid: 613a04428f842fe1   # get from https://www.addthis.com/

Notes: choose one of sharejs/addthis; enable: true uses AddThis sharing; pubid is obtained after registering at AddThis.

Purpose: related post recommendations at the bottom of posts.

Config (theme config):

related_posts:
  enable: false
  title: 相关文章推荐   # custom header, empty = default
  display_in_home: false  # show on homepage too
  params:
    maxCount: 5       # max recommendations
    PPMixingRate: 0.25 # mixing ratio
    isDate: false     # show date
    isImage: false    # show image
    isExcerpt: false  # show excerpt

Notes: recommends by tag/category similarity; with display_in_home: true, homepage post cards also show related recommendations.

21. LeanCloud Read Count (leancloud_visitors)

Purpose: LeanCloud-based post read count (the data source when post.meta.views.source: leancloud).

Config (theme config):

leancloud_visitors:
  enable: true
  app_id: v2hJTCLDHLnGF4iSJkBJ8mga-MdYXbMMI
  app_key: Hu4UNHLVERHkhfH6G5xqdqN3

Notes: after enabling, set §2 post.meta.views.source to leancloud for it to take effect; this blog uses umami by default, this config is kept as a backup.

22. Google AdSense (googleAd)

Purpose: Google AdSense ad slot on post pages.

Config (theme config):

googleAd:
  enable: false
  adClient: "ca-pub-2899930387274309"

Notes: adClient is the AdSense publisher ID (ca-pub- prefix), obtained after registering at Google AdSense. The config comment marks it “not yet complete”.

Appendix: Post Page Config Quick Reference

Config itemLocationDescription
Post heropost.banner_img etc.per-post override via front-matter banner_img
Author/datepost.meta.author / post.meta.datedate format "LL a"
Word count/timepost.meta.wordcount / post.meta.min2readawl 1 / wpm 300
Viewspost.meta.viewssources umami/busuanzi/leancloud/waline
Updatedpost.updatedoff by default, front-matter updated overrides
TOCtocper-post off via front-matter toc: false
Commentspost.commentstype: waline, front-matter comments controls
Rewardpost.rewardWeChat/Alipay payment QR
Copyrightpost.copyright (with license sub-key)per-post override via front-matter reprintPolicy
Mathpost.mathspecific: true + front-matter mathjax: true
Diagramspost.mermaidspecific: true + front-matter mermaid: true
Prev/next, outdate, category bar, adspost.prev_next / outdate / category_bar / advertisementssee the Layout & Pages chapter
Comments
Data Loading...