Vibelog: Weatherpatch - UI Improvement

A few weeks ago, I vibe-coded a web-app called Weatherpatch. This is an app that is designed to receive email newsletters and produce them as an RSS feeds: basically what Feedbin does, but without needing to use Feedbin. The app was vibe-coded with Opus, and while functional, it is hardly an example of good design (unless you’re a fan of Cubism). To wit:

Auto-generated description: A user interface displays an inbound email address for subscribing to newsletters and options to manage feeds, including renaming, deleting, and merging them.

Yeah, Opus just threw the feed management controls all over the place. And I tolerated it for a time. I was more interested in having something functional, rather than pretty. But the thing about a bad UI is that it makes using the app feel bad. Sure I’m not in there managing feeds, but I would like to go in there are copy-paste the email address when setting a new one up.

Seeing that Fable is available again (thanks, US government, I guess?) and that I haven’t given it a proper shakedown test last time, I figured it was worth throwing it at the problem, and seeing if it could fix the design Opus threw together. I also wanted to try out the frontend-design plugin. Here’s the initial prompt:

The UI design of this webapp is quite primitive. While functional it doesn’t make it pleasant to use. Can you propose an improved design? Don’t change the underlying technology: just the UI and styling.

It took a while, but came up with the following diagnosis:

Fable’s diagnosis of the issue

What makes the current UI feel primitive

Looking at the templates, three things stand out:

  1. It’s stock Pico. Default palette, default type — it looks like every Pico demo, with no identity of its own.
  2. Every feed card shows its full management UI all the time. Each card carries a rename input, rename button, delete button, merge dropdown, and merge button — with ten feeds that’s fifty always-visible controls for actions you perform maybe once a month. The thing you actually want from a feed (its URL) is buried among them.
  3. Raw 60-character URLs dominate every card. The random slugs are unguessable by design, which means they’re also unreadable — printing them in full conveys nothing.

Proposed direction: “Synoptic chart”

The name weatherpatch is a gift — the app is essentially a weather station for newsletters, with feeds as stations reporting in. The direction leans into meteorological chart vernacular, kept quiet and instrument-like, since this is a tool you visit briefly, not a marketing page.

  • Palette — cool “chart paper” background (#F4F7F6), slate ink (#22303A), isobar blue for links (#33636F), and one accent: RSS orange (#D95B10). The orange is subject-grounded — the whole point of the app is producing RSS — and it’s used sparingly: the logo dot, the copy button, focus rings, the RSS chip.
  • Type — IBM Plex Sans for UI, IBM Plex Mono for everything machine-ish: the inbound address, URLs, section labels. Monospace is load-bearing here, not decorative — the app’s most characteristic artifacts are random strings. (In production I’d embed the woff2 files in static/ alongside the CSS so the single-binary, no-CDN property holds; system-font fallbacks if you’d rather add zero bytes.)
  • Signature element — the inbound address as a station call-sign: a hero panel at the top of the dashboard with the address in large mono type, one prominent “Copy address” button, and a faint set of isobar contour lines etched behind it (inline SVG, centre labelled “1013”). One place of boldness; everything else stays disciplined.

The UX changes (bigger win than the styling)

  • Progressive disclosure. Rename/merge/delete move behind a native <details> “Manage” disclosure per card — no JavaScript needed, and each card collapses to one line: title + two chips.
  • URLs become copy chips. RSS and JSON chips copy the URL on click (your existing data-copy handler works unchanged — the chips just carry the attribute). The full URLs remain visible as plain links inside the Manage panel for the times you want to open or inspect them. Copying is the primary use of a feed URL, so it gets the primary affordance.
  • A real empty state and a properly styled login card with a styled error alert (currently an inline style=“color:#b00020”).
  • Microcopy tightened throughout: “Give this address to every newsletter you subscribe to. New senders show up below as feeds.”

What stays and what changes

Everything server-side stays as-is: Go templates, Fiber, embedded assets, POST-redirect-GET forms, app.js patterns. The change is replacing pico.min.css (~80 KB) with a hand-rolled weatherpatch.css (~8 KB) — same delivery mechanism, and at three pages the custom stylesheet is small enough to own outright. Template edits are modest (the <details> structure, chips, hero panel).

Two optional extras that would touch Go code lightly (no technology change, just flagging since you said UI-only): per-feed item count and last-received date — the data is already in SQLite and would make the dashboard feel like stations actually reporting — and a favicon route using the RSS-arcs logo mark.

It also produced a mockup in a static HTML file, which was quite an improvement over what was there. I then went back and forth with it a couple of times, asking it to move command arguments to modals, and have it produce a mock with more than a handful of items:

Okay, that’s a good start. I do wonder if it’d be worth merging the actions onto a single line. Maybe have “Rename, Merge” on the left and “Delete” on the right. The Rename and Merge buttons will display modal dialogs prompting for the input: a text field rename, and a select list (not a drop-down) for the merge. Delete will be on the right, and show a confirmation dialog as a modal. Use HTML dialog elements for this. Add any JavaScript you need, but keep it vanilla JavaScript.

[…]

Can you demonstrate how this would look with 30 feeds? I just want to make sure the Merge feed can handle that many feed items in the modal. I’m think we need to make sure the list doesn’t grow too large.

I include in this gallery various screenshots in how the mocks evolved during this time.

After about half an hour of this, it was good enough to get Claude to implement it. I deployed the changes, and now the UI looks pretty decent.

So all in all, I’m impressed. I would like to know how much of this was down to Fable, and how much of it was the frontend-design plugin. I don’t expect to be using Fable often, given how expensive it is. But for a large job like this, it did a good job.