aphid 0.2.1

aphid 0.2.1 is a small content-polish release. Five additions, all backward-compatible: deeper wiki-links, stable heading anchors, a cleaner way to point an author at a profile URL, social-card meta tags emitted on every page so shared links get proper previews, and reading-time estimates on blog posts.

Wiki-links now accept an in-page anchor after the slug:

[[configuration#authors]]
[[configuration#authors|the authors section]]

The anchor text is slugified the same way as auto-generated heading ids, so [[page#Hello World]] resolves to #hello-world. A bare cross-page anchor renders as Page Title > section so the reader knows which page they’re heading to; pipe-alias to override.

Same-page anchors work too:

Jump to [[#summary]].

Backlinks are unaffected — the anchor portion is stripped before the link is recorded, so backlinks still aggregate at page granularity.

Custom heading IDs

Append {#custom-id} to any heading to override its auto-generated anchor:

## Configuration reference {#config-ref}

Renders as <h3 id="config-ref">. Custom ids are used verbatim — no lowercasing, no slug normalization — so {#API_v2.1} stays API_v2.1. Custom and auto ids share the same per-page namespace, so collisions still get -2, -3, … suffixes.

The two features compose. Give a heading a custom id, then target it from elsewhere with [[page#stable-id]] — rephrasing the heading text won’t break the link.

[[authors]] entries now support an explicit link:

[[authors]]
name = "Alice"
link = "https://alice.example.com"
email = "alice@example.com"

Templates receive author.link as the URL for the author’s profile. When link is unset but email is, author.link falls back to mailto:{email} — matching the previous behaviour, so existing configs keep working unchanged. When neither is set, the author name renders as plain text.

The bundled themes wrap the author avatar and name in <a href="{{ author.link }}"> when present. Custom themes that referenced author.email directly should switch to author.link; the value is the same in the email-only case.

Social card meta tags

Every page now ships OpenGraph and Twitter card meta tags in the <head> — so a link shared in Slack, Discord, Mastodon, iMessage, Bluesky, etc. renders a preview card instead of a bare URL.

Blog posts mark themselves up as og:type=article and emit article:published_time, article:modified_time, article:author, and article:tag tags from frontmatter. Other pages mark themselves up as og:type=website. Titles, descriptions, and images fall back through page → site config sensibly:

TagBlog post sourceOther pages
og:titlefrontmatter titlepage title, then site_title
og:descriptionfrontmatter descriptionsite description
og:imagefrontmatter imagesite social_image
og:urlabsolute URL of the postabsolute URL of the page

A new optional config field sets the site-wide image fallback:

social_image = "/static/social-card.png"   # root-relative URL or absolute URL

Recommended dimensions are 1200×630 px — the summary_large_image Twitter card format that most platforms render best. When no image is configured anywhere, the card downgrades to summary and the og:image / twitter:image tags are omitted.

Custom themes inherit the behaviour automatically by extending base.html. To override the type or add per-page tags, override the og_type and article_meta blocks — see Themes for the full block list.

Reading time

Blog post templates now receive a reading_time_minutes variable — an integer estimate based on word-count of the body, divided by the assumed reading speed, rounded up (minimum 1). The bundled themes render it inline with the publication date:

<span>{{ reading_time_minutes }} min read</span>

The reading speed defaults to 200 wpm (conservative, suits technical writing with code samples) and is tunable via a new reading_wpm config field — raise it for prose-heavy sites:

reading_wpm = 250

Custom themes can render the variable however they like. See Themes for the full per-template variable list.

Upgrading

cargo install aphid --locked --force
aphid --version

One small config tweak: author image paths no longer get a magic /static/ prefix — write them as /static/authors/alice.jpg (the same convention blog hero images and favicon use). The new social_image follows the same rule. Custom themes that read author.email should also switch to author.link.

See also: Wiki Links, Markdown > custom-ids, Configuration.