← All Tools

Why the Slug Generator Doesn't Turn café into caf-zrich

Guide · Last verified Aug 26, 2026

Say you're turning the blog title "Café Zürich" into a slug. The simplest possible implementation is a single regex: "strip anything that isn't a letter or digit." Do that, though, and é and ü vanish entirely, leaving the nonsensical result "caf-zrich." The original letters were just deleted — not converted to "e" or "u." The proper way to solve this is Unicode NFD normalization, and the Slug Generator actually uses exactly this approach.

1. The root cause: an accented character is a "different" character

A person reads é as "e with an accent on it," but to a computer, é is fundamentally its own, completely separate code point (U+00E9). A regex like [^a-z0-9] filters it out because é doesn't fall in the a-z range — it just gets deleted, not replaced with "e." Strip é out of café and you're left with "caf"; strip ü out of Zürich and you're left with "zrich," producing the unreadable slug "caf-zrich."

2. Unicode normalization: splitting one character into two pieces

Unicode has two ways to represent the same letter. One stores é as a single code point (U+00E9, the composed form, NFC). The other stores it as two separate code points: e (U+0065) plus a combining acute accent mark (U+0301) — this is NFD, Normalization Form Decomposition. Both look identical as é on screen, but the underlying data is structured completely differently. JavaScript's String.prototype.normalize('NFD') decomposes a string into that second form: base letter plus combining mark.

The core idea: decompose with NFD and é splits into two separate characters — the base letter "e" and the combining mark U+0301. Once split, you can target just the combining mark with a regex and remove it, leaving the base letter "e" intact.

3. A regex that removes only the combining marks

Unicode groups combining diacritical marks together in a dedicated block, code range U+0300 through U+036F. After decomposing with NFD, removing only characters in that range with a regex leaves the original base letters (e, u, n, c, and so on) untouched and strips only the accent marks. The result is the natural conversion people expect: é → e, ü → u, ñ → n. Unlike blindly deleting non-ASCII characters, this approach "strips the decoration" rather than "deleting the letter."

StepcaféExplanation
Originalcaféé is a single code point (U+00E9)
NFD normalizationcafe + ́decomposed into e (U+0065) and combining accent (U+0301)
Combining mark removedcafeonly characters in U+0300–U+036F are deleted
Naive deletion without NFDcafé is dropped entirely — the wrong result

4. What the slug generator's code actually does

Inside this tool's generateSlug() function is the line v.normalize('NFD').replace(/[̀-ͯ]/g,''). This decomposes the string with NFD, then uses a regex to remove only characters in the U+0300–U+036F range (combining diacritical marks). This step runs before the "remove special characters" option, so text like café or Zürich doesn't lose its letters entirely — it naturally becomes cafe and zurich. After that, if "remove special characters" is enabled, anything besides letters, digits, whitespace, hyphens, and underscores is stripped, and finally consecutive runs of whitespace and separator characters are collapsed into whichever separator you chose. As the codebase confirms, the actual implementation does use .normalize('NFD').

5. Why non-Latin scripts like Korean and Chinese are handled differently

NFD normalization only helps with Latin-family accented characters that have a "base letter + diacritic" structure. Korean (Hangul) and Chinese characters were never built from a separable base-letter-plus-accent structure, so NFD doesn't decompose them at all — they simply fall outside the letter/digit range at the "remove special characters" step and get deleted as-is. So if you need an SEO slug from a Korean title, it's recommended to translate or transliterate it into English first and then run it through this tool. If you also want to polish the title itself before turning it into a slug, the SEO Title Generator is a useful companion.

Frequently Asked Questions

Q. Does it matter whether I use NFC or NFD?

A. Yes, order matters. To strip a combining mark, the text has to be decomposed into NFD first. In composed form (NFC), é is already a single code point, so there's no separate combining mark to remove.

Q. Does this handle every accented character?

A. Most Latin Extended characters that decompose into a base letter plus a combining mark — é, ü, ñ, à, ç, and similar — are handled correctly. A character like German ß (eszett), which isn't a base letter plus an accent but its own distinct letter, won't decompose under NFD and may be left as-is or removed.

Q. Is a hyphen or underscore better for SEO?

A. Google treats a hyphen (-) as a word separator but reads an underscore (_) as joining two words into one. Hyphens are recommended for search visibility, and this tool defaults to hyphens.

Q. Can I regenerate the slug for an already-published post with this method?

A. If the conversion logic changes and the slug comes out different, you must set up a 301 redirect from the old URL to the new one. Changing the slug without a redirect can break existing backlinks and search rankings.