URL strategy

The canonical URL should usually come from the content path. A Markdown file’s location and filename are the source of truth unless the page has a real routing requirement that the filesystem cannot express cleanly.

Stable URLs#

A URL is not just an address; it is part of the public record of a page. When someone links to a page, saves it in notes, cites it in a document, or sends it in a message, the address becomes part of the work’s usefulness. If the address breaks, the content may still exist, but the connection is damaged.

Every piece of information has one canonical home: the URL where it is maintained over time. Other pages can summarize it, other platforms can syndicate it, and shortcuts can point to it, but one URL stays the preferred place to link, revise, and preserve the work.

  • keep public paths predictable
  • use redirects when pages move
  • avoid platform-specific slugs when a simpler local path will do
  • preserve old URLs when external links may already exist
  • treat aliases as maintenance, not clutter

Path conventions#

Visitors rarely arrive through the homepage. They come through links, search results, bookmarks, and old references; a conventional location is one nobody has to be told. Some paths are load-bearing because everyone expects them: /about, /blog, /contact, and /privacy.

Directory names separate collections from individual resources:

  • Plural for collections: navigational hubs and listing pages use plural nouns because they represent a bucket of items, such as /talks/, /projects/, and /tags/
  • Singular for single-instance pages: pages that represent one focused concept or administrative function use the singular form, such as /about/, /search/, and /contact/
  • The blog exception: individual articles sit under the historical /blog slug to keep essays cleanly isolated from documentation and data references

Root files and /.well-known/#

Tools do not guess; they expect specific files at exact locations. The long-established files stay at the site root, not under /.well-known/:

  • /favicon.ico for browser tabs, bookmarks, and search results
  • /index.xml or /feed.xml for standard syndication
  • /robots.txt for crawler access rules, standardized in RFC 9309 (2022) after 25 years as a de facto convention
  • /sitemap.xml for search engine visibility, per the sitemaps.org protocol

Newer site-level metadata belongs under /.well-known/, the namespace RFC 8615 reserves so a tool can find site-level metadata without scraping pages or guessing. The IANA Well-Known URIs registry lists the registered suffixes.

The surfaces this site publishes are documented in Machine-readable surfaces.

Default front matter#

Front matter should describe meaningful differences, not restate Hugo defaults.

Do not add these values when they are empty or false by default:

  • sitemap_exclude: false
  • description: ""
  • tags: []
  • empty aliases:
  • draft: false

Use these fields only when they change behaviour:

  • sitemap_exclude: true for pages that should render but stay out of the HTML sitemap and XML sitemap;
  • pagefind_exclude: true for pages that should render but stay out of search;
  • draft: true for pages that should stay out of normal production builds;
  • layout: when the page uses a special data-driven or bespoke layout;
  • type: when Hugo lookup or grouping needs a section type different from the physical section;
  • collection: when the page belongs to a real site collection such as references, slashes, or a blog series.

There is no content-page exception for draft: false. Use it only inside examples or documentation that are explicitly showing Hugo front matter states.

Front matter url#

Do not add url: when it only repeats the URL Hugo already creates from the mounted content folder, language suffix, section, filename, or _index directory.

Use an explicit url: only for real exceptions:

  • root machine-readable files such as /security.txt, /.well-known/security.txt, /humans.txt, /human.txt, /llms.txt, and /llms-full.txt, unless a dedicated output format or routing rule owns that path;
  • redirect stubs or compatibility pages whose file location is intentionally not their public path;
  • nested utility pages whose clean public path cannot be represented without making the content model worse, such as the contact confirmation pages under /contact/;
  • pages that must live at a nested URL that cannot be represented by moving the file without making the content structure worse.

Current intentional url: exceptions:

  • human*.en.md, humans*.en.md, llms*.en.md, and security*.en.md publish root machine-readable files on each site.
  • content/legal/privacy-redirect.*.md preserves the old root privacy path and sends visitors to the legal privacy notice.
  • content/blog/ref/phonetic-alphabet-world.*.md is physically near the related phonetic reference content but publishes as a regular blog article.

Front matter slug#

Use slug: when the page needs a localized or cleaner final URL segment while preserving the shared content structure between languages.

This is common on French pages: the file can stay paired with the English content file, while the visible URL segment can use the French term.

When a French page uses a localized slug:, keep the equivalent English-style route as an alias when someone may reasonably try it.

Front matter aliases#

Use aliases for alternate routes that should continue to resolve. They are useful when a page is renamed, moved, or likely to be requested through a popular short path. When structure changes, the old path does not break; it becomes a permanent redirect to the new one. Review 404 reports regularly to catch routes that should have been preserved.

None of this is free. Every URL promised to stay alive is maintenance owned forever, and a redirect map only grows. Not every link deserves a forty-year commitment, but a personal site should outlast three platform migrations.

On a bilingual site, some pages deserve a root-level alias because people may request the path that would exist on a monolingual site. The alias is a convenience route; the canonical page should still live under the language-prefixed URL.

Root-level aliases belong on the English page only. The English page may also keep language-prefixed /en/... variants for explicit redirects. The French page should use /fr/... aliases, and when it uses a localized slug:, it should keep an alias for the English filename in the same section.

Current intentional alias exceptions:

  • Mindmap pages keep legacy camelCase aliases such as /blog/macOSHistory/, /blog/mindmaps/macOSHistory/, and /blog/publications/macOSHistory/ as compatibility routes. Keep the English page as the owner of root aliases and mirror only language-prefixed /en/... and /fr/... variants on the matching language pages.

Blog URLs#

Do not add unnecessary blog url: values. Blog pages should follow the content path by default, so a page under content/blog/ref/airline-codes.en.md naturally owns /en/blog/ref/airline-codes/.

If a blog URL needs to differ from the file path, prefer first asking whether the file should move or whether slug: is enough. Use url: only when neither option expresses the route cleanly.

Physical location#

Put the Markdown file where the canonical URL should live. The folder gives context, ownership, and the URL prefix; the filename gives the final slug.

Reference indexes may still link to content that lives elsewhere. For example, the macOS technical-specifications reference lives at content/blog/macos/_index.*.md, while the archived release pages live beside it under content/blog/macos/. The data file stores those canonical archive links instead of forcing a second routing layer.

Use this pattern when a data-driven page is an index over related material, but the indexed pages belong to a cleaner topic or series URL.

Series filenames#

Inside a series or topic folder, do not repeat the series name in every filename. The folder already owns that part of the URL and context.

Prefer content/blog/files/naming-convention.en.md over content/blog/files/file-naming-convention.en.md, and content/blog/naming/naming-convention.en.md over content/blog/naming/naming-naming-convention.en.md.

introduction.*.md is acceptable as a filename inside a series because it gives the page a predictable first item. The rendered page title must still stand on its own in global lists, feeds, search, and sitemap output. Do not use title: "Introduction" for published pages; use a specific title and keep weight: -100 for ordering.

The Links section uses a two-step short URL structure: a concise shareable URL that records traffic on this site before the reader leaves for the external page.

Each entry in data/links.yml keeps one routing token, slug. The layout derives every short URL from it with hardcoded prefixes; do not store derived values such as linkShortURL or linkExtShortURL in the data file.

URLPatternExample
Local link pagehttps://bhdicaire.com/en/links/<slug>/https://bhdicaire.com/en/links/ttx9/
Local short URLhttps://dicai.re/l/<slug>https://dicai.re/l/ttx9
External short URLhttps://dicai.re/lnk/<slug>https://dicai.re/lnk/ttx9

Slug rules:

  • one token per entry, shared by the local link page and both short URLs
  • four random characters from the readable vanityURLs alphabet when not set manually
  • existing tokens stay stable; renaming a slug breaks published short URLs

The short URL registry lives in custom/v8s-links.txt in the dicai-re vanityURLs instance. Every item owns two paired records that share the same token:

PrefixTargetPurposeTag
l/<slug>The local link pageShareable permalink that records traffic on this site firstbhdicaire-link
lnk/<slug>The external URLDirect outbound shortcut that skips the local pagebhdicaire-link-ext

The l/ record notes its pair with external=https://dicai.re/lnk/<slug>, and the lnk/ record notes its pair with link=https://dicai.re/l/<slug>; the registry stays easy to scan without storing long external URLs in the notes field. npm run links normalizes the data file and upserts the paired records; npm run check:links validates the registry after changes.