cd /news/artificial-intelligence/i-vibe-coded-an-lm-arena-for-ai-comp… · home topics artificial-intelligence article
[ARTICLE · art-73553] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

I vibe coded an LM Arena for AI companion apps with Claude Code.

A non-programmer developer used Claude Code to build a community-voted leaderboard for AI companion apps, called NoFilterReview, featuring seven leaderboards with monthly snapshots and anti-cheat mechanisms. The project, built with Astro, Cloudflare Pages Functions, and D1, stores all raw vote events to detect fraud and allows rebuilding scores from history. The developer warns that renaming UI labels can silently break API keys when shipping code one cannot read.

read2 min views1 publishedJul 25, 2026

I can't write code. I've never written a line of it by hand.

I still wanted something that didn't exist: a leaderboard for AI companion sites that shows what was tested, when, and how many people voted. Most "Top 10 AI girlfriend apps" pages are affiliate lists with a number stuck on top. LMSYS Chatbot Arena does it properly, so I described that to Claude Code and we built it: seven leaderboards with community voting and dated monthly snapshots. Astro, Cloudflare Pages Functions, D1. No accounts, no login, no client framework. Voting is a static page and one POST.

Two things I learned from specifying all of it and writing none of it.

They all pay me affiliate commissions, so they all have a reason to send fake votes.

Ballots over the rate limit don't get rejected. They get written like any other ballot, they just never reach the table the score reads from. If I rejected them I'd have no record, and I couldn't tell you later how many got filtered or why. This way each board can show votes received and votes counted.

Ratings work the same way. Every submission is kept, and the current state is a derived table with one composite key:

ON CONFLICT(voter_id, app_id, category_slug)
DO UPDATE SET rating_event_id = excluded.rating_event_id, updated_at = excluded.updated_at

Vote again next month and the event is appended and the pointer moves, so nothing counts twice. If I find a cheating pattern later, the raw events are still there to rebuild from.

The code works. What almost broke it was a link between two things that look unrelated.

Each rating dimension sent a key to the API, and that key came from slugifying the label on screen. "Filter strength" turned into filter-strength

, which matched. Then I renamed the label for a reason that had nothing to do with the API: a 5 meant "never blocks you", so high was good, but "filter strength" sounds like high means more filtering. It read backwards, so I changed the words.

Every ballot in that category would have failed with a 400, because spicy

isn't a key the API knows, and nothing would have told me why.

If you're shipping code you can't read, that's the thing to watch for. Not code that's broken when it lands. Code that works and is wired to a word you'll change later without thinking about it.

Next is an agent harness that runs the same script against every site and scores the transcripts on memory, character consistency and image consistency, publishing the prompts and the transcripts with each run.

The boards are live at nofilterreview.com/rankings. Adult AI sites, so consider that your content warning. Try to break the vote system, I want to know where it gives.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-vibe-coded-an-lm-a…] indexed:0 read:2min 2026-07-25 ·