A scratchpad for poets & rappers — phoneme-aware rhyme-scheme detection.
Project description
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 uvicorn app:app --reload
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
ightintonight), 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/flight→AY T). Matched anywhere in a line — that's the internal-rhyme detection. - Slant rhymes share just the vowel run (
hold/coal). - Multisyllabic & multi-word mosaics —
placement 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 FastAPI 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 endingsGET /api/lookup?word=light&mode=rhyme|near|syn→ frequency-ranked rhymes / near rhymes (by syllable count) and WordNet synonymsGET /api/word?word=...→ pronunciation, senses, homophones
Everything is served locally — no external dictionary calls.
License
ISC. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rhymepad-0.1.0.tar.gz.
File metadata
- Download URL: rhymepad-0.1.0.tar.gz
- Upload date:
- Size: 39.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83667d2a12a3eb3a047527fca5eace00efdf987f3d89b659749a20c2c75e5b18
|
|
| MD5 |
8f5c851389d97b7a8e466431de5c72f1
|
|
| BLAKE2b-256 |
861c26853812e21a70d40ecbcda551d422fe91ca1e5bbcae9a28617f1ed05a71
|
File details
Details for the file rhymepad-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rhymepad-0.1.0-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cf254a27185d12a7815e16070945913c0d8af62ad4dc6b8a40de82ff70d200f
|
|
| MD5 |
b6d2a7ef823d3a6b4d94d98a8963b461
|
|
| BLAKE2b-256 |
5648ce6038dd76273abcf5ce459b66ad3674589aee70e5a7480e2d3f97249d02
|