Linking Guide

Markdown links, cross-references, anchors, and target directives

4 min read 869 words
Edit this page

Was this page helpful?

Note

Do I need this? Yes when linking pages in Markdown content. For Kida template functions and path resolution details, see Linking Reference.

Bengal provides multiple ways to create links between pages, headings, and external resources. Choose the method that best fits your use case.

Tip

Try it out: This guide includes a test target anchor that demonstrates arbitrary reference targets. Scroll down to see it in action!

Quick Reference

Method Use Case Syntax
Markdown Links Standard links, external URLs [text](url)
Cross-References Internal page links with auto-title [[path]]
External References Link to external docs (Python, NumPy, etc.) [[ext:project:target]]
Template Functions Dynamic links in templates {{ ref('path') }}
Anchor Links Link to headings [[#heading]] or #heading
Target Directives Arbitrary anchors mid-page :::{target} id
Target References Link to target directives [[!target-id]]

Use standard Markdown link syntax for external URLs and simple internal links.

MARKDOWN
[Visit GitHub](https://github.com)
[Email us](mailto:hello@example.com)

Absolute paths (from site root):

MARKDOWN
[Get Started](/docs/get-started/)
[API Reference](/docs/reference/api/)

Relative paths (from current page):

MARKDOWN
<!-- From docs/get-started/installation.md -->
[Quickstart](./quickstart.md)
[Configuration](../reference/config.md)
[Home](../../_index.md)

Path Resolution Rules:

  • .md extension is optional — Bengal resolves both page.md and page
  • Relative paths resolve from the current page's directory
  • ./ refers to current directory, ../goes up one level
  • Paths are normalized automatically (trailing slashes, etc.)
MARKDOWN
[Link text](https://example.com "Optional title")

Cross-references provide intelligent linking with automatic title resolution and O(1) lookup performance. Use them for internal page links.

Basic Cross-Reference

MARKDOWN
[[docs/getting-started]]

This automatically:

  • Resolves to the page atdocs/getting-started.md
  • Uses the page's title as link text
  • Handles path normalization automatically
MARKDOWN
[[docs/getting-started|Get Started Guide]]

The |separator lets you specify custom link text while still using intelligent path resolution.

If a page has a customidin frontmatter:

YAML
---
id: install-guide
title: Installation Guide
---

Link to it by ID:

MARKDOWN
[[id:install-guide]]
[[id:install-guide|Installation]]

Benefits of ID-based links:

  • Stable even if page path changes
  • Shorter syntax
  • Works across site restructures

Link to any heading in your site:

MARKDOWN
[[#installation]]
[[#configuration]]

This finds the heading text (case-insensitive) and links to it. If multiple pages have the same heading, it uses the first match.

Link to heading in specific page:

MARKDOWN
[[docs/getting-started#installation]]

Path Resolution

Cross-references support multiple path formats:

MARKDOWN
[[docs/getting-started]]        # Path without extension
[[docs/getting-started.md]]     # Path with extension (also works)
[[getting-started]]             # Slug (if unique)
[[id:install-guide]]            # Custom ID

Resolution order:

  1. Custom ID (id:xxx)
  2. Path lookup (docs/page)
  3. Slug lookup (page-name)

Broken References

If a cross-reference can't be resolved, Bengal shows a broken reference indicator:

MARKDOWN
[[nonexistent-page]]

Renders as: [nonexistent-page]with a visual indicator for debugging.

Link to headings within the same page or across pages.

Same-Page Anchors

MARKDOWN
[Installation](#installation)
[Configuration](#configuration)

Headings automatically get anchor IDs based on their text. For example:

MARKDOWN
## Installation

This heading gets ID: `installation`

Custom Anchor IDs

Use{#custom-id}syntax for custom anchor IDs on headings:

MARKDOWN
## Installation {#install-guide}

Link to it: [[#install-guide]]

Arbitrary Reference Targets

Create anchor targets anywhere in content (not just on headings) using the{target} directive. This is similar to RST's .. _label:syntax.

Syntax:

MARKDOWN
:::{target} my-anchor-id
:::

Example: Target Directive Usage

MARKDOWN
:::{target} important-caveat
:::

:::{warning}
This caveat is critical for production use.
:::

See [[!important-caveat|the caveat]] for details.

Reference Syntax:

Use[[!target-id]]to explicitly reference target directives:

MARKDOWN
[[!test-target]]              # Link with auto-generated text
[[!test-target|Custom Text]]   # Link with custom text

Why ! instead of #?

The!prefix distinguishes target directive references from heading anchor references:

  • [[#heading]] - References heading anchors (auto-generated or custom {#id})
  • [[!target-id]] - References target directives (explicit :::{target})

This eliminates collisions and makes your intent explicit.

Use cases:

  • Anchor before a note/warning that users should link to
  • Stable anchor that survives heading text changes
  • Anchor in middle of content (not tied to heading)
  • Migration from Sphinx (.. _label:) or RST reference targets

Anchor ID requirements:

  • Must start with a letter (a-z, A-Z)
  • May contain letters, numbers, hyphens, underscores
  • Case-sensitive in output, case-insensitive for resolution

Note: The target renders as an invisible anchor element. Any content inside the directive is ignored (targets are point anchors, not containers).

Try it: This page has a test target below. Jump to it: Test Target

This is a test target anchor. You can link to it using[[!test-target]]from anywhere in your site.

Cross-Page Anchors

MARKDOWN
[Installation](/docs/getting-started/#installation)
[[docs/getting-started#installation]]

Both syntaxes work. Cross-references are preferred for internal links.

See Also