We take the typical blog url design (/2024/08/14/slug) for granted but back in the very early 2000s pretty much every blog tool had its own URL design. Matthew Thomas back then took an inventory:<p><a href="https://web.archive.org/web/20030810201315/http://mpt.phrasewise.com/2003/07/26#a534" rel="nofollow">https://web.archive.org/web/20030810201315/http://mpt.phrase...</a><p>He was on the search for his ultimate blogging system, where this "cruft-free" URL structure should be used:<p><a href="https://web.archive.org/web/20051107103030/http://mpt.phrasewise.com/2003/05/02#a507" rel="nofollow">https://web.archive.org/web/20051107103030/http://mpt.phrase...</a><p>I could have sworn there was a changeset in which Matt Mullenweg was implementing those cruft-free URLs in his new fork called Wordpress, but trying for google for something with "Wordpress" from the early 2000s is basically impossible in 2024.<p>Update: I found this: <a href="https://ma.tt/2004/08/mike-on-uris/" rel="nofollow">https://ma.tt/2004/08/mike-on-uris/</a>
I found Notion's URL schema interesting as well. They have to contend with renames of pages, reorganisation of the hierarchy and all that. So they have something like:<p><pre><code> notion.so/:account/Current-Name-of-Page-:pageid
</code></pre>
where the name changes if the page is renamed, but the redirect works, as the page ID is unchanged. In fact, one can just use<p><pre><code> notion.so/:account/:pageid
</code></pre>
and gets redirected to the right page, or even<p><pre><code> notion.so/:account/Anything-else-:pageid
</code></pre>
works too...<p>This is very handy in my use cases, when various Notion data is extracted into another tool, reassembled, and then needed to have a link to the original page. I don't need to worry about the page's name, or how that name gets converted into the URL, or any race conditions....<p>The page hierarchy is then just within the navigaton, not in the URL, so moved pages continue to work too (even if this looks like a flatter hierarchy than it really is).<p>I'm sure there are plenty of drawbacks, but I've found it an interesting, pragmatic solution.
Back when I was working on GOV.UK Verify we had URLs that looked something like /verify-passport for English and /cy/verify-passport for Welsh. I made the decision that if readable URLs was a design goal they should be readable in both languages, and ended up localising them all to (for example) /verify-passport and /gwirio-pasbort. No idea if anyone ever noticed, but sometimes it’s nice to sweat the small stuff.
Shout out to the classic "Cool URIs don't change": <a href="https://www.w3.org/Provider/Style/URI" rel="nofollow">https://www.w3.org/Provider/Style/URI</a>
I’m glad this article mentions GitHub, who have had some of the best URL design I’ve ever seen, and have done since they first launched.<p>I use that ALL the time. I can navigate straight to any issue by typing a URL. I can switch to the “actions” view for a repo by adding /actions. I can see the file I’m looking at in a branch by editing the URL and swapping “main” for the branch name.<p>All available via the UI as well, but I interact with GitHub so often that the tiny efficiency boost I get from navigating by URLs really starts to add up.<p>I also trust them not to break links, based on their track record. My notes and blog posts and even my source code are full of links to issues or code snippets on GitHub.
I like that GitHub supports file-like suffixes to get different views of the same content.<p><a href="https://github.com/torvalds/linux/commit/{hash}">https://github.com/torvalds/linux/commit/{hash}</a><p><a href="https://github.com/torvalds/linux/commit/{hash}.patch">https://github.com/torvalds/linux/commit/{hash}.patch</a><p><a href="https://github.com/torvalds/linux/commit/{hash}.diff">https://github.com/torvalds/linux/commit/{hash}.diff</a>
An example of a not-so-great URL design: Amazon product links have an optional slug before everything else like `{slug}/dp/{id}`. So you end up copying a gigantic URL everytime you wish to share a product unless you use the share product button to get the shortened link.
> website under a .is domain (which is for Iceland, apparently).<p>I don’t super like repurposing country names like that. Including .io.<p>It feels this disregards the actual meaning of the extension while ignoring some very legal consequences to be under Indian legal system instead of EU or US.
Note, if you are using optional slugs or otherwise, you should have a canonical url in the header so that search results will be collated to a single canonical url.
Post author here. There are so many great additional examples of intriguing URL patterns in the comments here. TY everyone for sharing ones you remember!
The Reuters links are an example of good links IMHO. They're not earth-shattering, and follow some fairly generic guidelines, but work quite well.<p>Format is
reuters.com/:category/:headline:date<p>which is all you need to know what you're clicking on. For example, I don't need to describe this link in order for its contents - and its time-relevance - to be understood:<p><pre><code> https://www.reuters.com/world/us-navys-newest-air-to-air-missile-could-tilt-balance-south-china-sea-2024-08-14/
</code></pre>
Edit: they are a bit long, though, I suppose
These are my URL rules, in any project where I or my clients violate one of the rules - or their priority, we will regret it down the road.<p>URL-rules<p>URL-Rule 1: unique (1 URL == 1 resource, 1 resource == 1 URL)<p>URL-Rule 2: permanent (they do not change, no dependencies to anything)<p>URL-Rule 3: manageable (equals measurable, 1 logic per site section, no complicated exceptions, no exceptions)<p>URL-Rule 4: easily scalable logic<p>URL-Rule 5: short<p>URL-Rule 6: with a variation (partial) of the targeted phrase<p>URL-Rule 1 is more important than 1 to 6 combined,<p>URL-Rule 2 is more important than 2 to 6 combined,<p>URL-Rule 3 is more important than 3 to 6 combined,<p>URL-Rule 4 is more important than 4 to 6 combined.<p>URL-Rule 5 and 6 are a trade-off. 6 is the least important.<p>A truly search optimized URL must fulfill all URL-Rules.<p>My preferred URL structure is:<p><a href="https://www.example.com/%short-namespace%/%unique-slug%" rel="nofollow">https://www.example.com/%short-namespace%/%unique-slug%</a><p><a href="https://" rel="nofollow">https://</a> – protocol<p>www – subdomain<p>example – brand<p>.com – general TLD or country TLD<p>%short-namespace% – one or two letters that identify the page type, no dependency to any site hierarchy<p>%unique-slug% – only use a-z, 0-9, and – in the slug, no double — and no – or – at the end. Only use “speaking slugs” if you have them under your total editorial control.<p>i.e.:<p><a href="https://www.example.com/a/artikel-name" rel="nofollow">https://www.example.com/a/artikel-name</a><p><a href="https://www.example.com/c/cool-list" rel="nofollow">https://www.example.com/c/cool-list</a><p><a href="https://www.example.com/p/12345" rel="nofollow">https://www.example.com/p/12345</a> (does not fulfill the least important URL-Rule 6)<p><a href="https://www.example.com/p/12345-product-name" rel="nofollow">https://www.example.com/p/12345-product-name</a>
I might be an outlier, but I don't like slugs in URLs.<p>They make URLs unnecessarily long, often forcing people to use URL shorteners -- completely defeating the purpose.<p>They get awkward when the author changes the title. Other commenters mentioned some tricks to get around this issue, but all involve redirects. Cools URLs shouldn't change in the first place.<p>They don't copy cleanly if you use nonalphanumeric characters, as in nearly every language other than English.<p>Virtually nobody just looks at a URL these days anyway, with all the search engines, cute thumbnails, and OpenGraph metadata that provide a glimpse of the actual content for you before you even click on it. This is doubly true in the non-English-speaking parts of the world where a slug in a shared URL is often just a jumble of %HEX.<p>Hand-picked words in URLs are fine, e.g. /about/me. I'm only talking about autogenerated slugs for user-submitted content above.
Similar to the Slack example given in the post with /is/ URLs, KDE has /for/ URLs with pages which present the KDE project and software for various user profiles: developers, kids, scientists, students, creators, gamers, activists, etc.<p>See all these pages here: <a href="https://kde.org/for/" rel="nofollow">https://kde.org/for/</a>
Love this. A big miss teams have are with affiliate/refer a friend urls. Like if you think of your Uber referral code being 5 characters instead of a general 16 character hash. Shorter makes it easier for people to remember and share their code.<p>e.g. RJF01 vs ab0fhct99fh2h4fqi2fj9
Using a numeric ID + ignored path part is easy to implement, but actually using the textual part without an exposed ID seems more elegant to me. Tip for implementing that:<p>* have a separate table that maps slugs to IDs, allowing many-to-one relationship, because content's title will be updated, and you don't want to break old links.<p>* long slugs will get truncated by users. A zero-cost way to recover from that is `select id where slug >= ? order by slug limit 1`<p>* in either case don't forget to redirect to the canonical URL, so that people can't create duplicate or misleading URLs on your site.
From a URL=Resource perspective I don't love unstructured strings in the url because they make it trickier (never impossible) to extend with sub-resources. For example, if I have a url for a blog post with a slug, it's more difficult to represent a comment as a sub-record of that post:<p>`my.domain/post/123/my-great-slug-that-is-pretty-long-but-doesnt-matter/comment/456`<p>vs<p>`my.domain/post/123/comment/456`
What’s the best way to handle url slugs that change? For example, if I have www.example.com/page/foo, and the user changes that page’s title to bar, the slug updates to www.example.com/page/bar and anyone visiting the old url gets automatically redirected to the new one. But now the old slug of foo can’t be used again (without appending some unique identifier to it, like foo-th683gh9i).
I like the slack.com/is/ scheme that makes the resource into a simple, legible phrase. I do something similar on my site: everything in the "projects" category has a URL that starts with "what-about", e.g.: <a href="https://joeldueck.com/what-about/splitflap/" rel="nofollow">https://joeldueck.com/what-about/splitflap/</a>
I've come to regret that most of my projects have this URL design- mainly because it gets harder to track via third party analytics platforms like Sentry and Clarity.<p>eg. series/9876545678 and series/098767890 get treated differently and the analytics get difficult to merge. But really they're the same page just hydrated with different data.<p>Should've used query params, eg series?id=9876545678
Another interesting related area is designing URLs for third-party components.<p>Third-party component have to coexist with existing site navigation logic, so generally you can't safely add URL-based configuration to such a component.<p>Fortunately, configuration can now be stored in fragment directives in order to hide this from normal site routing. e.g.<p><pre><code> https://example.com/page#routing-info:~:additional-routing-info-for-third-party-component
</code></pre>
With fragment directives, location.href and location.hash exclude the additional content in the hash after :~:<p>This is used in Transcend Consent Management for configuring parameters to debug and simulate various privacy experiences[1].<p>1. <a href="https://docs.transcend.io/docs/consent-management/reference/debugging-and-testing#config-overrides" rel="nofollow">https://docs.transcend.io/docs/consent-management/reference/...</a>
I gotta say, Datadog does this pretty well. They manage all their state (just information state, not like user sessions lol) in the URL, which makes it easy to integrate with and dynamically generate links and share information, and manages to stay human readable.
The Slack URL scheme, and a few others mentioned in other comments take me right back to hp.com/go/<Insert Product>, so hp.com/go/proliant would take you to Proliant servers, maybe.<p>The idea was really cool, but from talking to people at HP at the time, the implementation was apparently a complete nightmare done with an insane number of rewrites. It was sort of a hit and miss if the thing you typed in after /go/ would actually take you to the correct location, if any.
I don't think will be relevant going forward, Safari already hides the URL beyond the domain name by default, and I presume other browsers do/will too.
I forget where I ran across it, but one interesting adoption of URL design is to make the root of the directory part of the site's domain name. I.e. there was someone's website that was shared on HN, where their name was assembled with the domain name, TLD, and some characters after the first slash:<p><pre><code> firstna.me/lastname/
firstna.me/lastname/about</code></pre>
One of my favorite blogs for "sentence URLs" is <a href="https://there.oughta.be" rel="nofollow">https://there.oughta.be</a><p>The projects formatted like: <a href="https://there.oughta.be/a/wifi-game-boy-cartridge" rel="nofollow">https://there.oughta.be/a/wifi-game-boy-cartridge</a>
One big question in URL design is this:<p>Do path parameters get to have / in their values?<p>Let’s say you have a link shortener service and want to allow users to define shortcuts like /mypath/:rest where rest is appended to example.com/<p>Now you’re in a very interesting position when it comes to resolving URLs.<p>Curious to hear folks with experience in this
I think the URL design of stackoverflow leavs room for improvement. The id should not be necessary. StackOverflow demands unique questions. If a question doesn't have a unique slug, is the question unique? Great URL design to me is if the slug is suffficient for uniqueness, without an id.
I can't check this because I'm on mobile, but I presume Stack Overflow uses a canonical tag in the HTML to state their preference that the longer version with the slug should be the default, because that's the one search engines use.
How about great email address design? Of course firstname@lastname.com is top tier. But there are some interesting hacks you can do, such as firstn@melastname.com if your last name domain isn't available.
> Granted, it can also be used deceptively. For example, this is the same URL as above but it portends completely different contents (without breaking the link):<p>> stackoverflow.com/questions/16245767/how-to-bake-a-cake<p>Fortunately for SO the fake slug is not preserved and redirects to the real one (so e.g. stackoverflow.com/questions/16245767/motheficker is <i>not</i> served from their site), much to the chagrin those of us with childish sense of humor who some 25 years ago enjoyed dynamically generated nonsense like:<p><a href="https://web.archive.org/web/20031007123544/http://john.isgay.com/" rel="nofollow">https://web.archive.org/web/20031007123544/http://john.isgay...</a>
Everything should be accessible via the identity of its composition (a hash or equivalent). Then all the data needed to render it be computed or downloaded from some peered cache (DHT).
It was cool to see Jessica Hische called out. We own a couple of her children's books. Always fun when my parenting and tech worlds collide in surprising ways.
When you want to "go run" but all you have is curl and a prayer<p><a href="https://goblin.run" rel="nofollow">https://goblin.run</a>
id's that skip the textual part on their lookup/url validation and also don't redirect are not ideal, probably as bad as soft 404s. Maybe not as bad for bots if the canonical tag shows the intended URL.<p>Personally I'd avoid using id's and use a 32-bit hash of the URL which is more or less as performant as a straight id lookup. I usually went with murmurhash.
Just remember to build localization into your URLs.<p>mysite.com/en-us/some-page
mysite.com/en-ca/some-page<p>You can 301 redirect some locale to your "base" URL if you want.<p>mysite.com/en-us/some-page > mysite.com/some-page<p>But don't stress too much. Google doesn't really care about URL content any more. People on phones don't care what your URL says. It's at most desktop users, and devs.<p>Don't stress localizing your URLs...<p>mysite.com/fr-ca/some-page is just as good as mysite.com/fr-ca/une-page... and the former is a lot easier to tie into email marketing variables.<p>Just keep your sitemaps in the localized folder.<p>mysite.com/sitemap.xml... just a link to the various localized sitemaps.<p>mysite.com/en-us/sitemap.xml etc.<p>By keeping sitemaps in a localized folder, it'll make it a lot easier for yourself as you go to register your site with each market's locale.<p>If you just have to localize URLs... consider doing what Amazon does and just tie the URL to an ID.<p><a href="https://www.amazon.com/Moen-One-Handle-Bathroom-Deckplate-84771BZG/dp/B0CFYPTKF8" rel="nofollow">https://www.amazon.com/Moen-One-Handle-Bathroom-Deckplate-84...</a><p>the above is the same as this... <a href="https://www.amazon.com/dp/B0CFYPTKF8" rel="nofollow">https://www.amazon.com/dp/B0CFYPTKF8</a><p>And you can put anything you want in the URL string, it just matches on the ID.<p><a href="https://www.amazon.com/literally-whatever-you-want-here/dp/B0CFYPTKF8" rel="nofollow">https://www.amazon.com/literally-whatever-you-want-here/dp/B...</a><p>“We use the words in a URL as a very very lightweight factor. And from what I recall this is primarily something that we would take into account when we haven’t had access to the content yet… [but] as soon as we’ve crawled and indexed the content there then we have a lot more information. And then that’s something where essentially if the URL is in German or in Japanese or in English it’s pretty much the same thing.”<p>- John Mueller, Google Search Advocate.