How We Build Fantasy Names Without Producing Gibberish
Most generators are a syllable blender. Here is the full method we use instead — sound rules, morpheme pools, and the four tests a name has to pass before it ships.
Type "fantasy name generator" into a search bar and you'll get a hundred pages that do the same thing: glue a random opening chunk to a random closing chunk and call it a dwarf. Most of the time it works, in the sense that a string of letters comes out. It just doesn't sound like anything a dwarf would actually be called. This is the guide we wish existed before we built our own D&D character name generator — not naming theory for novelists, but the actual mechanics: phoneme pools, combination rules, a culture layer on top, and four tests that catch garbage before it reaches a results card.
Everything below describes real code that runs on this site right now, not a hypothetical approach. We'll show the pools, the rules, and — because it's the most convincing way to make the point — what happens when you deliberately break one of those rules.
The problem with "random syllable" generators
Here's the shortcut almost every free generator takes: build one long list of "cool fantasy syllables," pick two or three at random, staple them together, capitalize the first letter. Ship it. The output looks like this: Xar'ithuun. Vloq'annath. Kyr'esh. Every one of them has an apostrophe doing the work an actual sound system should be doing — signaling "exotic" without committing to any real rule about how the language behaves.
A naming-language writer at learningelvish.com put a name on this failure mode: generated names that ignore the sound rules of whatever language they're supposed to evoke end up as what amounts to English with apostrophes bolted on. The apostrophe isn't a real glottal stop or a real consonant cluster — it's a placeholder for "I didn't want to think about this part." Quenya bans certain consonant clusters that Sindarin allows. Dothraki barely touches the letter p. A generator that doesn't encode any of that isn't modeling a language; it's shaking a bag of letters.
Our dwarf names don't get apostrophes. They get hard consonant clusters and closed syllables — Baerdur Ironmantle, not Ba'ir'du. Our elf names don't get random exotic spelling either — they get open vowels and liquid consonants, because that's the actual mechanism that makes a name sound elvish, not the letter y showing up three times.
Phonotactics, in plain terms
Phonotactics is just the set of rules for which sounds are allowed to sit next to each other, and where in a syllable they're allowed to go. English has plenty: you can start a word with "str-" (street) but not with "rts-". You can end a word with "-mp" (lamp) but you'd never end one with "-pm". Nobody taught you this rule explicitly. You absorbed it before you could read, and it's why "rtsalamp" sounds instantly, obviously wrong even though every individual letter is fine.
Every syllable has three possible parts. Take the English word "strong": the onset is str- (everything before the vowel), the nucleus is -o- (the vowel core), and the coda is -ng (everything after the vowel). A language's phonotactics is just the rulebook for what's allowed to fill each of those three slots, and — critically — which combinations across slots are banned even when each individual sound is fine on its own.
This is the entire idea our generators are built around. Instead of one messy list of "syllables," we keep separate onset, nucleus, and coda pools per race, and we only ever recombine within a race's own pools. That single decision is what stops a dwarf name from accidentally borrowing an elvish coda.
How we split a name into phoneme pools
Look inside src/data/dnd-character.ts, the engine behind our race-by-race D&D
hub, and you'll find a POOLS object keyed by race. Each entry has its own
onset, nucleus, and coda arrays, plus separate
last / lastEnd arrays for surnames. Nine races, nine independent
phonetic identities, none of them sharing a pool with another.
The human pool leans on onsets like "Ald," "Bren," "Dor," "Kel" — consonant-vowel openers that read as familiar Western-medieval. The elf pool swaps in "Ael," "Cael," "Lyr," "Sil" — softer onsets, more vowel-forward. The dwarf pool goes the other way with "Baer," "Brom," "Thor," "Trau" — heavier consonant weight up front. None of this is decoration; it's the actual data the build function draws from every time a name is requested.
| Race | Onset examples | Nucleus examples | Coda examples | Sound character |
|---|---|---|---|---|
| Human | Ald, Bren, Dor, Kel, Ser | an, ard, or, orn, wyn | ton, ford, wick, dale, hold | Balanced, medieval-familiar, easy to read on sight |
| Elf | Ael, Cael, Lyr, Sil, Uri | ael, iel, ith, ean, on | dar, lis, rin, thal, wyn | Open vowels, liquid consonants (l, r), few hard stops |
| Dwarf | Baer, Brom, Dar, Thor, Trau | ak, ek, im, or, ul | born, dur, grim, stein, rik | Hard consonant clusters, closed syllables, guttural weight |
| Halfling | Alt, Brim, Finn, Merr, Reed | al, el, ic, on, y | berry, brook, thatch, well, mead | Domestic, soft-edged, borrows English rural place-names |
| Half-Orc | Bra, Gru, Ket, Kru, Thok | ak, ork, oth, urk, urg | ld, rk, sh, sk, rd | Blunt, short, hard stops with almost no vowel padding |
You can see this same logic taken further in our high elf name generator, which narrows the elf sound system even more: given names like Faelaris, Sylanden, and Thalorion are built almost entirely from open vowels and the liquid consonants l and r, with barely a hard stop in the whole given-name list. That's a deliberate choice, not an accident — the code comment on the file says outright that high elves lean on those sounds "to keep every name singable." A name a court herald can pronounce in one smooth breath.
Why elves get liquid consonants and dwarves get hard clusters
Compare an elf onset list to a dwarf one and the design intent is obvious even without reading a line of documentation. Elf onsets — Ael, Cael, Lyr, Sil — are dominated by l, r, and long vowel runs, the consonants phoneticians call "liquids" because they flow into a following vowel without a hard stop. Dwarf onsets — Baer, Brom, Thor, Trau — stack stop consonants (b, t, d, g) and consonant clusters (br-, thr-, dr-) that force a small pause in the mouth before the vowel arrives. Say "Lyrael" and then "Baerdur" out loud. One glides. One lands. That difference is the entire cultural signal, encoded in nothing more complicated than which letters are allowed in the onset array.
Our dragonborn generator pushes the guttural end further still: prefixes like "Ghesh," "Rhog," and "Vor" paired with suffixes like "kax," "trin," and "vrak" produce names built almost entirely from hard, back-of-throat sounds — appropriate for a race whose voice box is closer to a dragon's than a human's.
Combination rules: not every onset fits every coda
Separate pools solve half the problem. The other half is that even within one race's own pools, not every combination sounds right, and blind random pairing will occasionally produce something clumsy. Our build functions handle this with two mechanisms working together: a retry loop and a duplicate filter.
Here's the actual loop from dragonborn.ts:
while (out.length < count && tries < count * 25) { ... if (seen.has(display)) continue; seen.add(display); out.push(...) }
Every candidate name gets checked against a seen set before it's accepted. If the
random draw produces a name that's already been generated in this batch, it's discarded and
the loop tries again — up to 25 attempts per requested name before giving up. This sounds like
a small technical detail, but it's the difference between a batch of eight distinct dragonborn
names and a batch where "Bharnar Kimtath" quietly shows up twice because nobody was checking.
The high elf generator runs the identical pattern:
build a candidate, check it against seen, retry if it collides, cap attempts at
count * 25. Two different races, same underlying discipline. It's not glamorous
work, but skip it and you'll eventually ship a "random" list of eight names with a repeat in
it — which is the fastest way to make a generator feel broken even when the phonetics are
perfect.
The D&D character engine adds one more constraint on top: syllable count itself varies
per call. Its buildFirstName function rolls 2 + (Math.random() > 0.6 ?
1 : 0) syllables, so most names land at two syllables and roughly 40% stretch to three.
A coda only gets appended to the final syllable, and only about 55% of the time. That single
line is what keeps every name in a batch from having the exact same rhythm — without it,
every human name would be precisely onset-nucleus-coda-ending, syllable for syllable, and the
whole batch would start to sound like a chant instead of nine individual people.
Layering culture on top of phonetics
Phonetics gets you a sound. It doesn't get you a naming system. A real culture doesn't just make noises that sound consistent — it wraps rules of inheritance, rank, and identity around those sounds, and that's the layer almost no generator (ours included, until recently) bothers to model. This is where our race-specific generators pull ahead of a generic "elf name" button.
Take the high elf generator. It doesn't just spit out
a given name — it optionally compounds a house name from two pools (houseA:
Sun, Star, Silver, Crystal; houseB: spire, crest, song, ward), producing surnames
like Starcrest or Silverward. Then it layers a tone on top:
Noble, Arcane, Ancient, or Martial, each with its own small pool of lore lines. The same given
name, Faelaris, reads completely differently depending on which tone attaches to it —
paired with Arcane it gets a line like "a name that hums faintly around spellbooks and
ley-lines"; paired with Martial it would instead read as something built to be shouted across
a shield line. Same phonetics, different culture.
The dragonborn generator goes even further, building
a three-part identity instead of one name: a personal name (from malePre +
maleSuf or the female equivalents), a clan name (a compound of
clanA + clanB), and — when you ask for the full form — a childhood
nickname drawn from a pool of 25 descriptive epithets like "Stormrider," "Emberheart," or
"Ironhide." Then a draconic ancestry gets attached: one of ten dragon colors, each carrying its
own lore temperament. A gold-lineage dragonborn reads as "noble, wise, and righteous"; a
black-lineage one reads as "cruel, secretive, and territorial." None of that is phonetic. It's
a cultural and biological layer sitting on top of a phonetic foundation, and it's the part
that makes a name feel like it belongs to a person with a history, not a string generator.
The four quality tests every name has to pass
Building good pools and combination rules gets you most of the way there, but it's still possible to write a phonetically "correct" pool and end up with output that reads flat, confusable, or unpronounceable at the edges. Before we ship a generator, every batch of test output gets run through four checks.
| Test | What it checks | Fail example | Pass example | How the engine enforces it |
|---|---|---|---|---|
| Pronounceability | Can you read it aloud on the first try, no stumble? | Vrknthar (four consonants in a row, no vowel anchor) | Bharnar (clear onset, vowel, closing consonant) | Coda only follows a nucleus; onset and coda pools are hand-curated per race, not free consonant strings |
| Cultural distinctiveness | Could this name be mistaken for a different race's output? | An elf name built from dwarf-style hard clusters ("Brakdurn") | Sylanden (unmistakably elvish: open vowels, liquid consonants) | Separate onset/nucleus/coda arrays per race; no cross-race pool sharing |
| Duplicate / collision | Does the same batch repeat a name? | A 6-name batch that quietly includes "Aldric Ashmoor" twice | Six requested names, six distinct results | seen Set checked before every push; retry loop up to count × 25 attempts |
| Rhythm and length | Does every name in a batch sound like the same three syllables on repeat? | Every result exactly two syllables plus one fixed ending | A mix of two- and three-syllable names, some with a coda, some without | Randomized syllable count (2, occasionally 3) and randomized coda inclusion (~55% chance) per build |
Notice that three of the four tests are things a human editor would have to eyeball on a finished batch — they're not things you can bolt on as a single line of validation code. That's why we test with real output, not just by reading the pool arrays and assuming they'll combine well. A pool can look perfectly reasonable on paper and still produce awkward pairings at the edges until you've actually generated a hundred names and read them.
A worked example: building the Dragonborn generator
It's easier to see the method end-to-end than to read about it in the abstract, so here's how the dragonborn name generator actually goes from empty page to finished output.
Step one: personal name phonetics. We pulled male prefixes and suffixes straight from the Player's Handbook naming convention, then extended the lists so the pool wouldn't feel thin after a dozen generations. Male prefixes: "Ar," "Bhar," "Ghesh," "Rhog," "Vor." Male suffixes: "ash," "kax," "nar," "trin," "vrak." Combine a prefix and a suffix and you get a name like Bharnar — no vowel padding needed because both halves already carry a vowel.
Step two: the clan compound. Clans get their own two-part pool, entirely separate from personal names, so a clan name never accidentally reuses personal-name syllables. "Kim" (clanA) plus "tath" (clanB) gives Kimtath. Put the two pieces together and you get a full name: Bharnar Kimtath — a personal identity plus a family line, the same two-tier structure real surnamed cultures use.
Step three: the childhood nickname. Dragonborn in this tradition also carry a third, informal name earned in youth — pulled from a pool of English descriptive epithets: "Stormrider," "Emberheart," "Ironhide." Request the "complete" form and you get Bharnar Kimtath "Stormrider" — personal name, clan name, and the nickname the character's family actually calls them.
Step four: draconic ancestry. Last, a lineage gets attached — one of ten dragon colors, each with a hard-coded temperament. Say Bharnar Kimtath rolls red ancestry: the badge reads "Red · chromatic" and the description reads "proud, fierce, and quick to wrath." A different roll, silver ancestry, would attach "kind, honorable, and steadfast" instead — same name, different implied personality, because the lineage layer is independent of the phonetic layer.
Put it all together and one generation might hand you Bharnar Kimtath, "Stormrider," red chromatic lineage — proud, fierce, quick to wrath. Four independent decisions (personal phonetics, clan phonetics, nickname pool, ancestry lore) stacked into one character, none of them stepping on the others.
Try it
Roll your own three-part dragonborn identity — personal name, clan, nickname, and lineage — in the dragonborn name generator.
Before/after: what gibberish actually looks like
The clearest way to show why the rules matter is to break one on purpose. Take the dragonborn
pools above and remove exactly one safeguard: the seen duplicate check and the
race-locked pool boundaries, so any onset can pair with any coda from any pool in the file,
with no retry logic at all.
| With the rules (real output) | Rules stripped (unconstrained blend) |
|---|---|
| Bharnar Kimtath | Bharel Kelthork |
| Uadjrila Vergath | Uadjbrek Dinbur |
| Rhogmed Turnric | Rhogstein Ashfordyn |
Read the right column out loud. "Kelthork" bolts a dwarf-flavored coda onto a dragonborn onset and produces a consonant pile no single race's phonotactics would generate on its own. "Ashfordyn" stitches a human place-name ending onto a dragonborn prefix and gets three unrelated sound systems arguing with each other in one word. None of these are unpronounceable exactly — that's what makes the failure sneaky. They're pronounceable and still wrong, because they don't belong to any one coherent sound system. That's the actual mechanism behind the "English with apostrophes" complaint: not that the letters are unreadable, but that the rules that should constrain them have gone missing.
Where the D&D Character generator differs
Not every generator on this site uses the same method, and that's deliberate. The D&D character name generator is what we call race-first: pick a race, pick a gender, get a name built from that race's phoneme pool and lore. It does not ask about class, and it does not attach class-flavored temperament to the output. A fighter and a wizard of the same race draw from the exact same name pool, because in the actual rules a barbarian orc and a wizard orc share a language and a culture, not a fighting style.
That's a contrast with something like a Baldur's Gate 3 companion generator, which would reasonably lean into class-specific flavor since BG3 characters carry a class identity as part of who they are. The point isn't that one architecture is right and the other is wrong — it's that the method has to match the target. A hub covering nine races needs pools that are directly comparable and swappable; a single-character generator built around one specific game's cast can afford to bake in more specific flavor. Building both with the same rigid template would make one of them worse.
You can see the difference directly: a Human result from that generator might read Aldric Ashmoor — "medieval roots, picked up across a dozen different cultures" — while a Half-Orc result from the exact same tool, same race-first architecture, reads Grukan Ironjaw — "blunt and functional, no wasted syllables." Same engine, same build function, radically different sound and lore because the pools underneath are completely separate.
How to judge any fantasy name generator (including ours)
You don't need to read anyone's source code to tell a well-built generator from a syllable blender. Run any generator — ours or a competitor's — through these five questions.
- Does it use apostrophes as a crutch? An apostrophe that doesn't correspond to a real glottal stop or syllable break is usually standing in for "we didn't build a sound system."
- Do two different races/cultures from the same tool sound distinct? Generate ten elf names and ten dwarf names back to back. If you can't tell which batch is which without the label, the pools aren't actually separated.
- Does a batch of eight ever repeat a name? Generate a large batch a few times. A repeat means there's no duplicate check, which usually means the tool wasn't built with production traffic in mind.
- Is every name the same length and rhythm? If every result in a batch is exactly two syllables with the same ending pattern, the tool is running one rigid template instead of varying structure.
- Is there anything beyond the name — lore, meaning, or context? A bare string of letters with no explanation of what it means or where it comes from is missing the layer that makes a name feel like it belongs to someone.
Run our own tools through the same five questions. That's not a rhetorical dare — it's the actual bar we hold ourselves to before a generator ships.
FAQ
Why do fantasy name generators sound fake?
Usually because they ignore phonotactics — the rules for which sounds can sit next to each
other and where. Random syllable combination without those rules produces strings that are
readable but don't belong to any coherent sound system, which reads to the ear as fake even
when you can't articulate why.
What is phonotactics in simple terms?
It's the rulebook a language uses for arranging sounds within a syllable — which consonants
can open a syllable, which can close it, and which combinations are banned even when each
sound is fine alone. English allows "str-" at the start of a word but never "rts-"; that's
phonotactics at work, and every invented language needs an equivalent rulebook or its names
will drift into noise.
Do fantasy names need to mean something?
Not always, but a system behind the sound helps more than a literal translation does. Our
dragonborn clan names don't have dictionary meanings, but they follow a consistent
two-part compound structure every time, which reads as a real naming convention rather than
noise — and layering an ancestry or tone on top (as our dragonborn and high elf generators do)
gives the name context even without a literal gloss.
Can two different races share the same generator?
Yes, if the pools underneath stay separate. Our D&D character hub covers nine races
through one build function, but each race pulls from its own onset, nucleus, coda, and lore
arrays — nothing is shared across races. The shared part is the mechanism, not the sound.
Why does my generated dwarf name sound like an elf name?
That's the cultural-distinctiveness test failing. It usually means the tool you're using
draws from one shared syllable pool for every race instead of keeping separate pools per
culture — check whether the same suffixes show up across races you'd expect to sound
different.
Sources and further reading
-
Our own generator code —
src/data/dnd-character.ts,src/data/dragonborn.ts,src/data/high-elf.ts, and the shared engine insrc/data/_engine.ts— is the primary source for every mechanic described above. - Best Fictional Language Name Generators, Compared — used here only to fact-check the term "phonotactic fidelity" as applied to Tolkien and Dothraki-derived generators, not as a source for examples.
- Phonotactics (Wikipedia) — a neutral reference for the general linguistic term used throughout this guide.
Generators from this guide
Put any of this into practice — every tool below is free and needs no sign-up.