My AIOS rewrite just grew a slick new Todo board — do-next ranking, tag bars, a detail drawer. Then I actually looked at a row and saw it: literal **asterisks** and `backticks` bleeding straight through. The todos had migrated from the old dashboard carrying their raw markdown, and every list row was rendering it as text. A UI that's meant to look done, quietly wearing its source code. This is the small, relatable "oops" — and the two-line-idea fix.
The todos came over from the old dashboard with their formatting intact — **bold**, `inline code`, the lot. In the old drawer that markdown got rendered. In the new Todo board's list rows, it didn't: the title was printed as a plain string, so the asterisks and backticks showed up as literal characters. Every row read like a diff of itself. Nothing was broken — it just looked unfinished, which on a UI that's supposed to look finished is its own kind of broken.
** and ` — and the rows printed them as-isThe bug was loud because the surface was new and dense. 3merged — the AIOS rewrite a fresh Claude model crowned the winner back in EP.30 — just earned its own dedicated Todo board (app/todos/page.tsx + TodosView.tsx, ~384 lines): do-next ranking, one-at-a-time show filters, clickable by-tag bars, and cards that open a detail drawer. A lot of rows, tightly packed — so a stray asterisk in every title wasn't a corner case, it was the whole wall. Good features are great bug-finders: they put the flaw somewhere you finally have to look at it.
The tempting fix is "render markdown everywhere." Wrong: a title row wants one clean line, not a mini-document with headings and code blocks. So the fix is a pair. A RichText renderer — mirrors the old dashboard's todo-drawer formatter — renders full markdown where there's room, the detail drawer. A plainTitle helper — strips markdown down to plain text — runs on every row title, wherever titles appear: Today rows, ActionableList, the Work view's next-action, Library rows. Render in the drawer, strip in the rows. One import came in dirty; the cleanup had to reach every place a title is shown, not just the board that made it obvious.
RichText formats the drawer; plainTitle cleans every row titleStripping markdown from a string is a few lines. The catch is that titles render in more places than the feature you're building — plainTitle had to be threaded through Today rows, ActionableList, the Work next-action, and Library rows too. Miss one and the asterisks reappear somewhere you weren't looking. A one-import bug becomes a five-surface fix.
One dirty row and its clean twin, the board the bug lived on, and the two tools — RichText to render, plainTitle to strip. Tap any image to enlarge it and read exactly what's on screen.




The todos didn't change; the way they're shown did. Rows render as one clean line, the drawer renders the full formatting, and the migrated markdown that was bleeding through is now handled at exactly the two places it should be. The meta-kicker writes itself: the rewrite a fresh model called the winner back in EP.30 isn't done winning — it's still absorbing lessons and shedding rough edges the judge never thought to test for. Winning once isn't the same as staying finished.
On camera: the slick new Todo board, the asterisks bleeding through every row, and the two-part fix — a RichText renderer for the drawer, a plainTitle helper for the rows.
If you've ever migrated content and watched raw markdown bleed into your UI, this is the whole fix in two pieces: a tiny renderer for the roomy surface, a tiny stripper for the tight one. Same source string, two jobs. Everything in this episode is free and open — clone it, run it, make it yours.
# Migrated content carries raw markdown. Don't render it everywhere:
# <RichText/> renders full markdown in the drawer · plainTitle(s) strips it for every row title (Today · ActionableList · Work · Library)
The extracted RichText + plainTitle snippet is being cleaned up for release. Comment RICHTEXT on the post and the bot DMs you the moment it's public.
A polished Todo board and a markdown fix are surface wins. The real prize the fresh model pointed at back in EP.30 is underneath: stop building more Next.js apps, move everything onto one SQLite spine with clean import/export. Core first, UI second — the migration parked to August, next up.