Linking

A robust linking system that survives content reorganization and works seamlessly in single-page applications.

In traditional websites, links are tied to URL paths:

[Installation Guide](/docs/getting-started/installation)
[Contact Section](/about#contact-form)

This works until you reorganize your content. Move "Installation" under a new "Setup" section? Every link breaks. Rename a page? Broken links. Reorder sections on a page? Hash links stop working.

Documentation sites are particularly vulnerable—content restructuring is routine as projects evolve. Maintaining hundreds of internal links becomes a burden that discourages improvement.

Stable References

Uniweb solves this with a stable reference system that decouples a page's identity from its location in the site hierarchy.

[Installation Guide](page:installation)
[Contact Section](page:about#contact)

These links resolve to the correct URL regardless of where the content lives. Move "Installation" anywhere in your site—the link still works.

How It Works

Section IDs (Automatic)

Every section gets a stable ID derived from its filename:

pages/home/
├── 1-hero.md         → #section-hero
├── 2-features.md     → #section-features
├── 2.5-testimonials.md → #section-testimonials
└── 3-cta.md          → #section-cta

The numeric prefix is for ordering only—the ID comes from the name part. You can freely reorder sections (change 2-features.md to 5-features.md) without breaking any links to #section-features.

Override when needed via frontmatter:

---
type: ContactForm
id: contact
---

Page IDs (Optional)

By default, pages are referenced by their route path:

[About Us](page:about)
[API Docs](page:docs/api)

For pages that might move, add an explicit ID in page.yml:

# pages/docs/getting-started/installation/page.yml
id: installation
title: Installation Guide

Now page:installation resolves correctly even if you later move the page to pages/setup/install/.

The page: protocol supports pages, sections, and combinations:

SyntaxResolves To
page:about/about
page:docs/api/docs/api
page:about#contact/about#section-contact
page:installationRoute of page with id: installation
page:installation#requirementsSame page, scrolls to requirements section

In Markdown Content

For setup instructions, see the [Installation Guide](page:installation).

Have questions? Visit our [contact form](page:about#contact).

Cross-Page Scrolling

When navigating to a page with a hash (e.g., page:about#contact), the runtime:

  1. Navigates to the page via client-side routing
  2. Waits for the page to render
  3. Smoothly scrolls to the target section

This works in both SPA mode (development) and with pre-rendered pages (production).

When to Use Explicit IDs

Section IDs are automatic—you rarely need to override them. Do so only when:

  • The filename doesn't reflect the section's purpose
  • You want a shorter/cleaner hash URL
  • Multiple sections could have similar auto-generated IDs

Page IDs are optional. Add them when:

  • The page is frequently linked to from other pages
  • You anticipate reorganizing your site structure
  • The page is part of a versioned documentation set
  • You want URLs to survive localization (same ID across /en/ and /es/)

Comparison with Other Approaches

ApproachProsCons
Path-based linksSimple, familiarBreak on reorganization
Link checking toolsCatch broken linksFix after the fact, maintenance burden
CMS-managed linksCentralizedRequires CMS, vendor lock-in
Uniweb stable IDsAutomatic, survives changesRequires page: protocol

Best Practices

  1. Use page: for internal links—plain paths still work but don't get the stability benefits

  2. Let section IDs be automatic—meaningful filenames like 2-features.md give you #section-features for free

  3. Add page IDs proactively for high-traffic pages in documentation sites

  4. Keep IDs short and descriptive—they appear in URLs when users share links

  5. Don't change IDs once content is published—they're part of your public API


See Also