What a slug is, precisely

In example.com/guides/how-to-tie-a-tie, the path is /guides/how-to-tie-a-tie and the slug is the final segment: how-to-tie-a-tie. It is the human-readable handle for one page, and unlike a title it is part of an address — which means it is subject to encoding rules, uniqueness constraints and the awkward fact that other people link to it.

The nine steps, in this order

Order matters, and most homemade slug functions get two or three of these wrong:

StepWhy
1. Normalise UnicodeSeparates accents from base letters so they can be handled
2. Transliterate or strip marksTurns é into e rather than deleting the letter
3. Lowercase, locale-independentlyA locale-aware lowercase corrupts Turkish text
4. Replace runs of anything else with a hyphenSpaces, punctuation, symbols
5. Collapse repeated hyphensOtherwise punctuation clusters leave gaps
6. Trim hyphens from both endsA title ending in a question mark leaves a trailing one
7. Truncate at a word boundaryCutting mid-word reads as a mistake
8. Guard reserved wordsA slug of admin or api can shadow a real route
9. Check uniquenessDifferent titles can produce identical slugs

Step three is the one with a real bug attached. If you lowercase using the user locale and that locale is Turkish, the letter i becomes a dotless ı, and every slug generated on that machine differs from the ones generated everywhere else. Slug generation is machine text handling, so it needs the locale-independent conversion.

Transliteration has no single correct answer

This is the part that tools quietly get wrong, because the right output depends on the language of the text, not on the characters in it:

InputNaiveLanguage convention
Münchenmunchenmuenchen (German)
Malmömalmomalmo (Swedish, not malmoe)
straßestraestrasse
Škodaskodaskoda
naïvenaivenaive

German convention expands the umlaut to a following e, so ü becomes ue. Swedish does not — ä becomes a. The same code point therefore wants two different outputs depending on which language the title is in, and no generator can infer that from the string. German ß is worse: dropping the mark leaves nothing, so a generator that only strips marks turns straße into strae, which is not a word in any language.

For non-Latin scripts there is no stripping possible at all. Greek has competing transliteration standards that disagree; Chinese requires word segmentation and a dictionary before pinyin can be produced. The two legitimate options are a language-specific mapping table you maintain deliberately, or keeping the native script in the URL.

Native script is more viable than it used to be. Browsers display Unicode paths readably, and search engines index them without difficulty. The trade-off is that the underlying URL is percent-encoded, so a six-letter Cyrillic or Arabic word becomes a long run of percent-escapes the moment somebody pastes the link into plain text or an email client — visually alarming even though it works. For an audience reading that script it is usually worth it; for a mixed international audience, transliteration is calmer.

Hyphens, underscores, and the advice that is half right

Use hyphens. The historical reason is that search engines treated a hyphen as a word separator and an underscore as a joiner, so my_first_post was read as one long token. The engines have largely converged and the ranking difference now is small to nonexistent, but the convention stands for two better reasons: hyphens are what everyone expects, and an underscore is frequently invisible in a URL rendered with an underline, so readers cannot tell whether the gap is an underscore or a space.

Never use spaces — they become %20 — and avoid anything from the reserved set, so no plus signs, ampersands, question marks, hashes or slashes inside a slug.

Where the standard advice goes too far

Stripping stop words is often a mistake. The common advice to remove and, the and a comes from an era of keyword-stuffed URLs. There is no ranking bonus for a shorter slug, and removing them can wreck the match with how people actually search: how-to-tie-a-tie mirrors the query, while tie-tie does not, and reads like a truncation error. Remove filler when a slug is genuinely unwieldy; do not remove it as a rule.

Slugs are not a ranking lever. A descriptive URL helps a person decide whether to click, and search engines have said readable URLs are preferable, but no amount of keyword packing in the path moves position. Search results often display a breadcrumb rather than the full path, so words beyond the first few are frequently not shown at all.

Dates in slugs age badly. A path with a year in it makes an updated evergreen article look stale and makes the URL wrong once you revise it.

Collisions, which happen more than you expect

Stripping punctuation collapses genuinely different titles. A guide to C++ and a guide to C# both slugify to c-guide, because both symbols vanish. So do Node.js Basics and Node JS Basics. Two real fixes: keep a small mapping so that plus signs and sharps become words such as cplusplus and c-sharp, and always check the generated slug against existing ones before saving, appending a numeric suffix when it clashes.

The reserved-word check matters too. A page whose title happens to be Admin, API, Login or Static can produce a slug that collides with an application route, which is either a broken page or, in a badly ordered router, an unintended one.

One more: a slug containing a Cyrillic character that looks identical to a Latin one produces two distinct URLs that are visually indistinguishable. Restricting output to a known character set closes that off.

Treat a slug as permanent

Once published, a slug is referenced by links, bookmarks, shared messages and search indexes you do not control. Changing it breaks all of them unless the old address keeps working through a permanent redirect — and even then, redirect chains accumulate and some referrers do not follow them.

The structural answer is to decouple identity from wording: a path of /123/my-article-title can resolve on the number alone, so the words can change freely while every old link still lands. If the slug alone is the identifier, plan on issuing a permanent redirect and keeping it indefinitely.

A related detail worth fixing once: on a case-sensitive server, /My-Post and /my-post are two different URLs serving the same content, which is a duplicate-content problem. Redirect anything with uppercase to the lowercase form, pick one convention for the trailing slash, and set a canonical link.

Questions people actually ask

Hyphens or underscores?

Hyphens. The ranking gap has narrowed but the readability and convention arguments have not.

Should I strip the small words?

Only if the slug is too long. Removing them from a short, query-matching slug makes it worse, not better.

Can I change a slug after publishing?

Yes, but budget for it: a permanent redirect from the old path, kept in place for good, plus updates to any internal links.

Is what I type here sent anywhere?

No. Slugs are generated in your browser and nothing is uploaded, logged or stored, so unpublished titles stay unpublished.

Keep exploring Gen Code Tools

Every tool comes with a written guide, and every category is one click away.