flove blog

The tag cloud and the playlist: how Risa's frontend grew up

Risa is, at heart, two pieces of frontend. On the left, a floating cloud of tags — little chips that drift around, that you tap to filter the feed, that grow when you ask them to. On the right, the playlist — the player, the threads, the reactions, everything that happens when a laugh is actually listened to. Over the last month that frontend went through three lives: it was born, it was moved into a shared engine, and it was cleaned until anyone could fork it. This is the story of those two pieces across the versions — and the three names you need to keep straight: flove0 (the distro), risa1 (nick as tag), risa2 (the current one, on the shared libraries).

By the numbers

flove0 — the shelf

Before the apps, the container: flove solo, a downloadable, local-first package you unzip and run without the internet. A flat zip (flove-solo.zip), a service worker that precaches the whole catalogue, a home page that reads like a catalogue, and an Android wrapper. flove0 is the shelf the apps sit on — which is why the shelf’s most public frontend growing up matters to the whole family.

risa1 — where the tag cloud and the playlist were born

risa1’s idea was nick as tag: a serverless Telegram bot turns your voice note into a clip, a moderator approves it, and it lands in risa.json for the web to read. The backend deserves a paragraph, not a chapter — upload → moderate → ffmpeg → R2 → feed → channel, with a salted key per author, a miniapp, and anti-abuse limits. And it kept getting ongoing fix and improvement releases (v1.0.1 → v1.0.7): accessibility to zero violations, RSS/Atom feeds, CI on every push, the critical bot fix, drafts that no longer vanish between cron runs, video-notes, the community users, the threads. Good, boring reliability work — the kind that makes a frontend safe to love.

The subdomain: from a hash to a home

The deepest identity promise in risa1 is the author subdomain. Every published clip carries a salted key (never the Telegram id in the clear), and with a key the author’s name links to #/u/<key>, an automatic mini author-page that aggregates all their laughs. The subdomain is that page promoted to a home of your own: after the first publication the bot offers <username>.liberada.net with a three-way prompt — “Sí, quiero / No sé / No, seguro” — and nothing auto-creates. “Sí” activates the subdomain; “No sé” asks again at the next publication; “No, seguro” silences it forever. A /usuario <nombre> command renames it, and the publication notice hands the author their link (“Puedes encontrar todas tus risas juntas en este enlace: …”). The miniapp (#/entrar) ties the 6-digit code from the bot to that key, so you can see your own page before the world does. It’s opt-in all the way down: privacy is the default, the address is the gift.

But the frontend is where risa1 is remembered:

And then risa1 was frozen — a version you intend to keep trusting, packaged as the download.

risa2 — the tag cloud and the playlist move to the shared engine

While risa1 was being polished, its future was being built in parallel: Cloudflare D1 (a real database for follows, reactions, plays), a service worker for offline, and authy (claims, several ids, central/users/). risa2 is not a bump — it’s another line of life, and its story is mostly told in the frontend.

The subdomain grows a brain

The subdomain that risa1 promised as an opt-in link became, in risa2, a real architectural feature. A Worker serves a generic profile template for any username in usernames.json, so <user>.liberada.net works without a folder per person — the profile is served, not stored. The template resolves the user from the Host header (<user>.liberada.net) as well as the path, so the same code answers the apex and every subdomain. Aliases ride on top: an author can have several names — María, her yoga-handle, a private alias — each filtering the same feed from the same canonical profile. The DNS moved from IONOS to Cloudflare to make it real, the canonical profile lives on the subdomain, and the identity that makes it all hang together is authy: claims, several ids, and central/users/<key>/ waiting in the wings. The tag cloud filters laughs; the subdomain filters people — and now the whole liberada network is addressable by name.

The human pass — the playlist learns to react

The frontend’s last act in this window is the one people actually feel:

Then a long, loving polish pass, all of it on those two pieces: a centred topbar with the transport where your thumb expects it, the + that became a perfect circle, the play button and Publicar and the Go button all agreeing on a single red, hover and click effects that stopped disagreeing with each other, emojis that bob and grow on hover, a Porque that throws its benefit chips down at its own pace.

The thread

Three names, one frontend. flove0 is the shelf. risa1 proved the tag cloud and the playlist — and the subdomain that gives every laugher a home — and froze them when they were trustworthy. risa2 moved both into a shared engine, set them on D1, service workers and a Worker that serves a profile for every name, and cleaned them until anyone could fork the whole thing. Ama is next: paused for now, waiting its turn on the same two pieces and the same promise of an address you can point people to.

Come poke around — Risa is live (tap the tags, play the world playlist), the apps catalogue is getting more honest, and the docs try hard to explain it before we’ve finished it. Download the distro, break a chip, tell us what you’d relate differently. It’s one determined human and one alarmingly patient robot, and we’re only as good as the next person who forked us.

slow it · flow it · love it.

← all posts