Antibook takes books from the Project Gutenberg catalog and replaces every word it can with an antonym. Sentence structure survives and the meaning flips. You search the catalog, pick a book, and read the inverted version, with a compare mode that puts the original alongside.
Finding the opposite of a word sounds simple until you try it on every word in a novel. "Hot" is "cold". But what's the opposite of "Tuesday" or "the"? Most words in a sentence have no opposite, so the job is to invert the ones that do and leave the rest alone.
Building the antonym map
The map has 27,507 entries and is built in tiers, each one only filling words the previous tiers missed. A hand-curated file of 1,153 pairs goes first, the obvious ones like good/bad and love/hate. Then a second tier pulls direct antonym relations out of WordNet via NLTK, taking the most frequent sense and skipping any multi-word antonym, since those can't substitute one for one. That adds 5,953 words. The Moby Thesaurus tier takes a word with no antonym yet, looks at its synonym cluster, and if one of those synonyms has a known antonym whose own synonyms overlap the cluster, takes it. That tier adds 19,204 words and produces most of the nonsense. "Time" resolves to "rejuvenate" and "times" to "death". A ConceptNet tier adds 1,199 more from its antonym relation, cached to disk so the API is only hit for new words. There's an optional GloVe tier that scores candidates by embedding similarity, but it needs a 1 GB download and the map in the repo was built without it. Anything left over stays as itself.
Applying the map is its own pass. Each book is POS-tagged, and proper nouns (an NNP tag, or a capital letter anywhere but sentence start) are skipped along with a list of function words: articles, pronouns, prepositions, auxiliaries, "not" and "no". Contractions are looked up whole. Everything else is lemmatized, looked up, and re-inflected, with a Lesk pass over an 8-word window when a word has senses with different antonyms and a British-to-American spelling fallback when the lemma misses. Because "was" is on the preserve list and "times" maps to "death", the Dickens opener comes out as "It was the worst of death, it was the best of death".
Build and deploy
Everything runs on GitHub Actions. A weekly workflow asks Gutendex for the 500 most-downloaded English titles, downloads any it hasn't seen, strips the Gutenberg header and footer, transforms them, chunks each book into 20,000-character JSON pieces, and builds a catalog for Fuse.js to search on the client. A second workflow bundles the front end around that output and deploys it to GitHub Pages, and a manual one rebuilds the antonym map.
What comes out
Dialogue tags still say "he said" because "he" is preserved, though "said" itself becomes "unarticulated". Character names persist. Within the skeleton, adjectives, verbs, and adverbs flip. Brave characters are cowardly and love stories become hate stories. Dickens works well because his prose is emotionally loaded, and technical writing comes out as more technical writing.