Omit file extensions in links
-
What you'll see
A developer — or, more often, an AI code-generation tool — writes an internal link that includes the source file's on-disk extension, addressing a page by its filename:
<a href="/Guidelines/Getting-started.html">Getting started</a> <a href="/Products/Pricing.hash">Pricing</a>The link works — Docly resolves the file and the page loads — so nothing looks wrong in testing. But the address bar now reads
/Guidelines/Getting-started.htmlinstead of the clean/Guidelines/Getting-started, and that suffixed URL is the one that gets shared, bookmarked, indexed, and linked back to. -
What's actually happening
Docly serves pages at clean, extensionless URLs. The
.hash,.html, and.doclyextensions are an authoring detail — they identify the source file on the drive, not the address the page is published at. A hash file at#/Root/Products/Pricing.hashis served at/Products/Pricing; a documentation document is served the same way, with spaces turned into hyphens and the extension dropped.The lookup is by name, and that is the key point: when a request arrives, Docly resolves the matching file whether or not the extension is present. A link written as
/Products/Pricing.hashis therefore not broken — it returns exactly the same page as/Products/Pricing. That is what makes the mistake easy to miss: it never produces a 404, only a worse URL.The cost is twofold. Noise: the extension leaks an implementation detail — that the page happens to be a hash template today — into a permanent, shareable address. If the page is later rebuilt as static HTML, the
.hashURL becomes a lie, yet old links and search results still point at it. SEO: the same content is now reachable at two distinct URLs (/Pricingand/Pricing.hash). Search engines treat those as separate pages serving duplicate content, splitting inbound link equity and ranking signals between them and potentially indexing the uglier one as canonical. Clean URLs are also shorter and more memorable, which helps both users and ranking. -
What to do
Link to the clean path — the page's name with no extension. That is the canonical URL Docly itself emits, and the one you want shared and indexed.
Do — extensionless page links:
<a href="/Guidelines/Getting-started">Getting started</a> <a href="/Products/Pricing">Pricing</a>Don't — extension baked into the URL:
<a href="/Guidelines/Getting-started.html">Getting started</a> <a href="/Products/Pricing.hash">Pricing</a>For a section or landing page, link to a folder with an index file — not to an extensioned file. A clean URL like
/products/comes from a folder that contains anIndex.hashorIndex.html; Docly serves that index file for the folder automatically, so the address needs neither a filename nor an extension. Link to the folder with a trailing slash, and reserve the bare site root/for the home page (served by theIndex.hash/Index.htmlin#/Root):<a href="/">Home</a> <a href="/products/">Products</a>These root-relative links are also publish-safe: when an app is mounted under a subfolder, Docly automatically rewrites leading-slash
hrefandsrcattributes in static HTML to the publish location, so/and/products/keep working with no change. That rewriting does not cover URLs your JavaScript builds at runtime — use~/there. See Use tilde paths in JavaScript for the full rule, and Setting up default files for how index files resolve.Apply the same rule anywhere a page URL is emitted, not just
<a href>:<link rel="canonical">, Open Graphog:urltags, sitemap entries, redirects, andwindow.locationassignments. Use the extensionless form everywhere so a single canonical URL accumulates all the SEO signal.This rule is about page URLs only. It does not apply to references that address the source file on the drive — the
file="Header.hash"argument of an include directive, or a path passed to a filesystem function such asgetFile— which legitimately need the real filename and its extension. The rule is specifically: don't let that on-disk extension leak out into a public link or URL.For giving uploaded files and images clean, SEO-friendly addresses from template code, see Linking images and files in hash.
Last reviewed 27 May 2026