The Philosophical Developer — Chapter 64: The Word Processor That Learned a Poem Is Not a Paragraph
2026-10-18 · 6 min read

Hugh Howey gives away NEO, his word processor, under MIT — and it is very good at novels, screenplays, and KDP pipelines. But the poet I build for writes poems, and in NEO a poem is a paragraph that behaves badly. So Rhema (ῥῆμα — “the word”) is now public: a word processor where the poem is a first-class object, desktop binaries built by CI, and an honest alpha banner on the door.
A new project, not a fork
The first decision was identity, and I made it harder than it needed to be. Rhema is not a thin fork with the name changed in the README. Every identity-bearing thing — product name, app id, artifact names, desktop entry, updater channels, user-visible URLs — is Rhema’s own. Upstream NEO stays whole and MIT-credited, but syncing it is now a cherry-pick discipline, not a merge. There is a file in the repo (RHEMA-ANCHORS.md) that maps every place we touched upstream code and how each touch survives a cherry-pick. It is the cheapest insurance in the project.
The stone that changed the design: a menu is not a manuscript
The language model had a wrong assumption baked in — spellcheck follows the interface language. The correction came from watching how a real writer lives in the app: she keeps the menus in English because that is what her hands know, and writes in Greek because that is what her poems are. Switching the UI language must never move the dictionary. A menu is an on-demand preference; a writing language is a property of the book.
So each book declares its own language set, chosen from the fifteen dictionaries we bundle. Spellcheck union-accepts: a word is correct if any declared dictionary knows it. The safety floor is absolute — a correctly spelled foreign word must never be flagged, because flagging it tells the poet a lie. The primary language drives suggestions and quote style; the interface locale never enters the pipeline. And the choice is permanently editable after book creation, because books grow second languages the way people do.
The gate: four reviewers, every phase
Every phase of this project ships through four adversarial reviewers — coding, security, UI, UX — who read the diff and the rendered app, not my summary. They were not polite, and they were right, every round. The catches worth retelling:
A stale test pin. We un-gated the Language menu for first-run users; a different e2e suite still asserted the old hidden behavior and failed. The lesson: a test that pins yesterday’s UX is a landmine, and the pin file has to be part of the change.
A prototype-chain hole. The spellcheck dictionary whitelist checked SPELL_LANGUAGES[code] — truthy for __proto__ and constructor. One line of validation (Object.hasOwn) and a unit pin closed it. Nobody exploited it; it existed for exactly as long as it took a reviewer to find it.
A test that raced its own product. The union-acceptance e2e waited four seconds and read stale spell marks — the dictionary load is async and the modal closes before it lands. The product was correct; the harness was lying. Deterministic failure, then a deadline loop that waits for the expected change.
An installer that could follow a planted symlink. sed … > ~/.local/share/applications/rhema.desktop is a habit worth unlearning; the fix writes to mktemp and installs into place.
The release pipeline taught me GitHub three lessons
Tag v* triggers builds for Linux (AppImage x64+arm64), Windows (installer+portable) and macOS (unsigned dmg+zip), then a release job publishes. It took three failures to go green: electron-builder tried to publish the release itself and wanted a token it should not have (--publish never — the release job publishes, the builders build); the release job had no checkout, so gh release create could not infer the repo (-R "$GITHUB_REPOSITORY"); and the runner warnings were not cosmetic — ubuntu-latest migrates to Ubuntu 26 on October 19, so the workflow pins ubuntu-24.04 and pins every action by commit SHA. Bleeding edge gets its own lane (a canary workflow runs the latest versions on purpose); the supported lane is specific versions.
The icon: SDXL cannot hold a straight line
The shipped NEO nautilus is beautiful but not ours. I generated four concepts locally with ComfyUI (SDXL, 1024²) and sent them, with 16/32/64/128/256 px legibility strips, to an expert design review. All four failed the brief: gradients baked into “flat” marks, accidental letterforms, a spiral that collided with the Instagram glyph. The reviewer’s verdict was blunt — for flat geometric marks, diffusion is the wrong tool; hand-author the SVG. So the icon is now a hand-authored SVG: an Archimedean spiral uncoiling into a straight horizontal line — the nautilus becoming verse, one monoline stroke, flat gold on dark ink, pixel-checked at 16 px. The generator is a small Python script that computes the geometry; nothing about it is accidental.
The honest bit
Rhema is alpha. The README says so in one section: as-is, no liability, built for one working poet and tested on her books, not hardened for the world. macOS binaries are unsigned (right-click → Open), the mobile sibling is parked on purpose, and the disclaimer rides in every release body automatically. Your words are recoverable inside the app — Darlings, trash, snapshots — and you should still keep your own backups. That is what alpha means when you say it out loud before someone finds out the other way.
Underneath: 245 unit tests and a dozen e2e suites that drive the real Electron app, green on every push.
Try it
github.com/dark5un/rhema — Releases has the binaries for Linux, Windows and macOS. Poetry is a first-class format; the paragraph never has to pretend again.
And if you would rather be shown than dig: rhema.guide — the product site, tutorials in English and Greek, screenshots of the real app, no account and nothing phoning home.
Sources
- https://github.com/dark5un/rhema — Rhema: word processor for books and poetry, public alpha
- https://rhema.guide — the Rhema product site (Hugo on GitLab Pages, EN+EL tutorials)
- https://github.com/hughhowey/neo — Hugh Howey’s NEO (MIT), the body Rhema grows a poetry format onto
- https://github.com/actions/runner-images/issues/14748 — the ubuntu-latest migration that made pinning runners non-optional