Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Meme Reply

Say anything — in Russian or English, out loud or typed — and it comes back with a line. Always with the source named.

Live: https://sgauruseu.github.io/meme-reply/

CI


What it does

  • Listens. Web Speech API, no key, no backend. Russian or English.
  • Answers on topic. It does not fire a random quote at you: it scores what you said against a tagged corpus and picks a line that is actually about the same thing, then shows you which words earned the match.
  • Goes to the internet when it has nothing. If the local corpus has no relevant line, it fetches a fresh joke from one of three live APIs. The network is an enhancement, never a dependency — unplug it and the app still answers everything.
  • Speaks the answer in a voice matching the language, and says so plainly when the device has no such voice instead of reading Russian in an English accent.
  • Names every source. Author, work, licence, on every single reply.

Two honest limitations, stated up front

Speech recognition is not local. In Chrome the audio goes to Google's servers. The app says so above the microphone button, before you ever press it. Firefox never implemented the API at all, so there typing is the only input — and typing is a first-class path, not a consolation.

The live joke APIs are English only. That is why the Russian side is a bundled corpus rather than a search. Two of the best-known quote APIs, quotable.io and zenquotes.io, were tested and rejected outright: neither sends CORS headers, so a static site cannot call them at all.

Where the lines come from

Every bundled line is public domain, and every one is attributed:

Russian English
Русские пословицы English proverbs
Козьма Прутков Mark Twain
А. П. Чехов Oscar Wilde
Н. В. Гоголь Ambrose Bierce, The Devil's Dictionary
И. Ильф и Е. Петров George Bernard Shaw, Jerome K. Jerome, Benjamin Franklin

Nothing is scraped from a meme site, nothing is a song lyric, nothing is by a living author. Proverbs carry no named author by nature, which also makes them immune to the misattribution that plagues quote collections online.

Live jokes come from icanhazdadjoke, Official Joke API and DummyJSON, each credited on the reply it produced.

How the matching works

  1. Detect the language. Two alphabets, so counting letters beats any model. Transliterated Russian (privet, kak dela) is caught by a short marker list.
  2. Tokenize and stem. Suffix trimming, run twice — Russian stacks endings, so работаю sheds ю to reach работа and must shed а again to reach the stem работе also reaches. One pass leaves those in different buckets, which is a bug the tests caught.
  3. Score by TF-IDF. A term shared with two entries out of eighty says far more than one shared with thirty. Tags count double: they are editorial judgement about what a line is about, while the body text merely contains words.
  4. Pick among near-ties at random, so the same input does not always return the same line, and exclude the last six replies so no proverb comes back twice running.

Randomness is a parameter, not a call to Math.random — which is the only reason a function whose whole job is to be unpredictable can be unit-tested at all.

Architecture

src/core/       pure: language detection, stemming, matching — no network, no DOM, no clock
src/corpus/     the bundled lines, with tags and attribution
src/adapters/   speech recognition, speech synthesis, live APIs, localStorage
src/ui/         React, presentation only

ui → adapters → core, never the reverse, enforced by an ESLint rule rather than by good intentions. 55 unit tests cover the core, including regression cases for the two bugs the suite actually caught: the Russian stemmer splitting word forms, and function words like need hijacking matches ("I need more coffee" once answered "a friend in need is a friend indeed").

Running it

npm install
npm run dev        # http://localhost:5173
npm test           # unit tests
npm run typecheck && npm run lint && npm run build

Node 22 or newer. Chrome or Edge for voice; any browser for typing.

Privacy

No backend, no account, no analytics. Settings and conversation live in localStorage, under keys prefixed meme-reply: — every GitHub Pages project site on an account shares one origin, so an unprefixed key would collide with the neighbouring app. Outbound requests: the live joke APIs, and whatever your browser's speech recognition does with your audio.

Code is MIT licensed — see LICENSE.

Built for the Enonic AI Hackathon

Specification in PRD.md; the agent working agreement is in CLAUDE.md.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages