RhymePad

A scratchpad for poets & rappers that does live phonetic rhyme analysis of whatever you're writing. Type or paste lyrics into the pad and the rhyme structure is color-coded as you type — end rhymes, internal rhymes, slant rhymes, multisyllabic and multi-word rhymes — using the actual sounds (CMU Pronouncing Dictionary + a g2p phoneme fallback), not the spelling.

Yes, it knows orange rhymes with door hinge.

Live at https://rhymepad.org.

Run

$ uv run granian --interface asgi --reload app:api

Then open http://127.0.0.1:8000.

The visual language

  • Color = which sound. Every rhyme family gets its own hue.
  • Brightness = rhyme strength, per word. Perfect rhymes blaze, slant rhymes sit back, consonance fainter still — and within a family the perfect anchors out-glow the loose slant attachments.
  • A faint underline marks the rhyming tail of a word (under ight in tonight), so you see exactly where the rhyme lands.
  • Gray fill = a dead line ending that rhymes nothing.
  • Dotted gold = a near-miss — a dead ending that's one phoneme from rhyming with another ending (e.g. hand/bond). A tiny edit locks it.
  • Hover any word and its whole family brightens across the page.

Toggles for rhyme · alliteration · rhythm (syllable-emphasis dots, "sheet music for your flow"). Hovering a word also names its family in the readout. Everything you see exports to a pixel-matching PNG.

How rhyme detection works

Every word is mapped to its CMU phonemes (pronouncing), with lyric-friendly fallbacks (runnin'running, possessives, made-up words via g2p-en).

  • Perfect rhymes share everything from the last stressed vowel on (tonight / light / flightAY T). Matched anywhere in a line — that's the internal-rhyme detection.
  • Slant rhymes share just the vowel run (hold / coal).
  • Multisyllabic & multi-word mosaicsplacement of creation, orange / door hinge — match across word boundaries.
  • Consonance catches shared vowel+coda endings (bliss / exist).

The engine is taste-tuned toward what a listener actually hears: rhymes don't cross stanza breaks, vowel families stay local, repeated refrains are muted, and dialect mergers (NEAR vowel, cot-caught, nasal and sibilant codas) are folded in. It deliberately rejects naive vowel-matches — garbage/javascript, middle/unavoidable, and smell like a do not rhyme, even though a coarser engine would link them.

( parentheticals ) are real lyrics; inline (ad-libs) rhyme internally but never claim the line-ending slot. Lines starting with # (your notes) or [ (section headers) are skipped.

Using the engine without the web app

The rhyme engine is a framework-free module — no FastAPI, no HTTP:

import rhymes

result = rhymes.analyze_text("an orange door hinge\nporage")
# token spans, rhyme groups (with strength), schemes, meter,
# alliteration, near-misses, unanswered endings

rhymes.lookup_data("light", mode="rhyme")   # ranked rhymes
rhymes.word_data("orange")                  # phonetic anatomy

app.py is just the Responder shell around it.

There's a CLI too:

$ rhymes analyze song.txt     # color-coded rhyme families, in your terminal
$ rhymes density *.txt        # which verse is the most rhyme-dense?
$ rhymes json song.txt        # the full analysis payload

(uv run rhymes … inside this repo, or pip install rhymepad once it's on PyPI.)

API

  • POST /api/analyze {"text": "..."} → token spans, rhyme groups (with family strength), per-stanza schemes, per-line meter, alliteration, near-misses, and unanswered endings
  • GET /api/lookup?word=light&mode=rhyme|near|syn → frequency-ranked rhymes / near rhymes (by syllable count) and WordNet synonyms
  • GET /api/word?word=... → pronunciation, senses, homophones

Everything is served locally — no external dictionary calls.

License

ISC. See LICENSE.

S
Description
No description provided
Readme ISC 32 MiB
Languages
Python 60.1%
JavaScript 30.7%
HTML 8.6%
Dockerfile 0.4%
Makefile 0.2%