Last updated July 11, 2026
Page Features
4 minutes read
Table of contents
Write at least one heading in your page body and folio.md adds a navigation panel on the right side of the layout automatically, visible on wide screens. It lists every h1 and h2 heading and highlights the section you’re currently reading as you scroll.
Headings deeper than h2 are intentionally excluded to keep the panel scannable. The auto-rendered page title doesn’t count toward the heading list.
Heading anchors
Every heading gets a shareable anchor link, generated from the heading text. Hover over any heading to see the # icon, then click it to navigate or copy the URL to share a link directly to that section.
Examples of how heading text becomes an anchor:
| Heading text | Generated anchor |
|---|---|
# Getting Started | #getting-started |
## How to set up? | #how-to-set-up |
### What's next! | #whats-next |
Reading time
folio.md adds an estimated reading time below every page title, for example 3 minutes read, or 1 minute read for short pages. The estimate counts words in the page body, excluding code blocks and inline code, at 200 words per minute.
To show the author’s name alongside the reading time, add author: to your page settings. The two items appear on the same line separated by a ·.
Last updated date
folio.md adds a “Last updated” date to every page automatically, reading it from your git history. It uses the date of the most recent commit that touched each file.
folio.md formats the date using the seo.locale value from folio.config.ts, defaulting to en-US. It omits the date when git history isn’t available, for example on a host that checks out without history.
Link validation
folio.md checks every link in your pages at build time. If you rename or delete a page, the build reports exactly which links to update so you can’t accidentally publish a dead link.
| Link type | Behavior |
|---|---|
| Internal path | Error if the target page doesn’t exist. Build fails. |
| Internal path with anchor | Error if the target page or heading doesn’t exist. Build fails. |
| Anchor-only link | Error if the heading doesn’t exist on the current page. Build fails. |
| External URL | Warning if the URL is unreachable. Build continues. |
mailto: link | Skipped, not checked |
External links open in a new tab automatically and carry a screen-reader label (opens in new tab).
Redirect pages and link validation
When a page uses the alias: setting to redirect to another page, folio.md validates the redirect target too. If the target doesn’t exist, the build fails.
If a redirect page has body content below the settings block, the link validator emits an ALIAS [non-empty] warning, because that body never renders:
ALIAS [non-empty] docs/old-page.mdx
has alias → /new-page but also contains body content (body will never be rendered)If another page links to a redirect page rather than to its destination, the link validator emits an ALIAS warning:
ALIAS [internal] /old-path → /new-path
in docs/some-page.mdx (link to the destination directly)Linking to redirect pages instead of their destinations is an antipattern. Update those links to point to the destination directly.
How redirects work
folio.md scans every page’s settings for alias: at build time and registers static redirects. The server handles the redirect with no JavaScript involved. folio.md excludes redirect pages from navigation, search, and prev/next pagination.
Copy code button
Every code block in your pages gets a Copy button automatically. Clicking it copies the raw code to the clipboard without any syntax-highlighting markup and gives brief visual feedback that the copy worked.
View transitions
folio.md uses Astro View Transitions (opens in new tab) to animate navigation between pages. Clicking any internal link replaces only the changed parts of the page rather than doing a full reload, which makes navigation feel instant. The sidebar, navbar, and cookie banner persist across transitions without re-mounting.
View transitions need no configuration and are active for all pages by default.