I do SEO for my own side projects, and for years I bounced between rank trackers. The expensive ones (Ahrefs, Semrush) are overkill when all I want is "did my 200 keywords move today?". The cheap ones had two recurring problems that drove me up the wall:
- "Daily" that wasn't daily. A lot of budget trackers quietly refresh every 2–5 days and still call it daily. When you're reacting to a Google update, that lag is the whole game.
- Billing friction. Cancel-by-email-only, surprise charges after you thought you'd stopped, keyword counts that double-count mobile vs desktop so your "250" is really 125.
So I started building the thing I actually wanted. It's called RankLoop, and this is the build log — the stack, the decisions, and the unglamorous parts that turned out to matter most.
I'm writing this at the start, not after some victory lap. No revenue screenshots here. It's live, the free plan is open, and I'm looking for people to poke holes in it.
The one design decision everything else hangs off
Most trackers store your position for a keyword: "you're #7." I decided to store the entire top 10 of every search, on every check.
That sounds like a lot more data (it is), but it's the feature I always wished I had: when you drop from #4 to #7, you can look back and see exactly which page moved in above you and when. Ranking is relative — knowing "I dropped" is useless without "because these three competitors climbed."
Concretely, each check writes a row with the keyword, your position, and a JSON snapshot of the top 10 (URL + title + position). History becomes a time series you can diff. It costs storage, but storage is cheap and the insight isn't.
The stack (and why, as a solo dev)
Nothing exotic. The bias was: fewer moving parts, fewer things that can page me at 2am.
- Next.js 16 on Vercel. App Router, route handlers for the API, one deploy target. As a team of one, "git push and it's live" is worth a lot.
- Supabase for Postgres + Auth + Row Level Security. More on RLS below — it's doing more work than any other single piece.
- Lemon Squeezy as the billing layer. This one deserves a paragraph.
- Resend for transactional email (alerts, welcome, support). This one deserves a cautionary paragraph.
Why a Merchant of Record instead of Stripe directly
If you sell software to people in the EU as a solo founder, you inherit VAT/tax obligations that are genuinely miserable to handle correctly. A Merchant of Record (Lemon Squeezy, Paddle) becomes the seller of record and handles that global tax mess for you. You trade a bit of margin for not having to become a part-time tax compliance department. For a one-person shop that trade is a no-brainer.
It also let me make cancellation self-serve from the dashboard in one click — which, given that billing traps were half my motivation, felt non-negotiable.
RLS is the whole security model, not a nice-to-have
Every table that holds user data (domains, keywords, checks, reports) has Row Level Security policies so a user can only ever read/write their own rows — enforced in the database, not in my application code. The app could have a bug; the database still won't hand user A's keywords to user B.
The subtle bit: the columns that decide a user's plan and billing status live on the profile row, and those are only writable by the service role (the billing webhook), never by the user's own session. Otherwise anyone could PATCH their own row to "plan: pro" and give themselves the paid tier for free. If you're building multi-tenant on Supabase, audit that specific thing — the gap between "RLS is on" and "RLS is actually scoped correctly" is where the bugs live.
The email deliverability rabbit hole
Here's the one that ate a full day and taught me the most.
Transactional email "works" in dev instantly, so you assume it's fine. Then you realize your first emails went out from a shared sandbox sender and landed straight in spam — because they weren't authenticated for your domain. Fixing it meant actually understanding the three records everyone waves at:
- SPF — which servers are allowed to send for your domain.
- DKIM — a cryptographic signature proving the mail wasn't forged in transit.
- DMARC — what receivers should do when SPF/DKIM fail, plus reporting.
Get those set up on your sending subdomain before you send a single real email, or you'll poison your domain reputation with your own test messages. Domain reputation is slow to build and slower to repair. I learned this the annoying way so you don't have to.
Where it actually is right now
Honest status:
- Free plan: 10 keywords, checked weekly, no card.
- Paid: $19/mo for 250 keywords daily across 5 domains; $49/mo for 1,000 keywords daily.
- Full top-10 history, one-email alerts (only when a keyword enters/leaves the top 10 or crosses your threshold — not daily noise), shareable read-only report links for clients, CSV export.
What it is not: a keyword research tool, a backlink index, or an all-in-one suite. It tracks Google positions reliably and gets out of your way. That's the whole pitch.
What I'd love feedback on
If you track rankings for your own projects or clients, I'd genuinely like to know:
- Is stored top-10 history something you'd use, or do you only care about your own number?
- What's the smallest feature that would make you switch from whatever you use now?
You can try the free plan (no card) at getrankloop.com and tell me where it falls short. I'm building this in the open, so critical feedback is the useful kind.
More build-log posts to come — next one is probably the scheduling layer that makes the daily checks actually fire on time, which was less trivial than I expected.
Top comments (1)
Since you asked what would make people switch: for me it's the stored top-10 history. A drop from 4 to 7 on its own says nothing about whether your page got worse or three competitors climbed past you, and that context is what cheap trackers never give. Also seconding your 'RLS is on' vs 'RLS is scoped correctly' line, the billing columns being service-role-only is the bit most Supabase tutorials skip.