How I Built saasdb.app in 11 Days Using AI-Assisted Development
A day-by-day build log of how saasdb.app — a public database tracking NRR, Rule of 40, and gross margins for 172+ SaaS companies — went from idea to live product in under two weeks.
I had the idea for saasdb.app on a Sunday evening while trying to answer a simple question: what's a "good" Net Revenue Retention number for a Series B SaaS company in the security sector?
The answer turned out to be scattered across quarterly earnings PDFs, paywalled analyst reports, and blog posts citing five-year-old benchmarks. No single place pulled it together into a queryable, filterable, up-to-date dataset. So I built one.
Eleven days later, saasdb.app was live with NRR, Rule of 40, and gross margin data for 172 public SaaS companies, a filter UI, a benchmarking panel, and a blog. Here's the unedited build log.
Day 1 — Scoping and data architecture
The first question was scope. How many companies? Which metrics? How would I source the data?
I landed on these constraints:
- 172 public companies — public filings are verifiable; private company metrics are guesswork
- Three metrics only: NRR, Rule of 40 (growth + FCF margin), gross margin
- Single snapshot in time: Q1 2025, sourced from most recent earnings
- CSV-first data model: easy to update, easy to verify, version-controlled
I spent day 1 designing the schema and stubbing out the CSV structure. No code written yet — just a spreadsheet with columns I was confident I could fill.
Defined schema: company name, ticker, sector (10 categories), ARR tier, NRR, gross margin, growth rate, FCF margin, Rule of 40 score, data source. Stubbed 30 rows to validate the model.
Day 2–3 — Data collection
This was the hardest part and the part that took the most time. Earnings transcripts, 10-Ks, and investor slides don't follow a consistent format. Some companies report NRR explicitly; others bury it as "net expansion rate" or "net dollar retention." Some don't report it at all.
I used a combination of SEC EDGAR filings, investor day presentations, and earnings call transcripts. For companies that don't report NRR explicitly, I calculated it from ARR cohort disclosures where available, or flagged it as estimated.
Roughly 23% of NRR figures in the dataset are my calculations or estimates, not direct company-reported numbers. I flag these. Any benchmark analysis you do with this data should treat estimated figures differently from reported ones. Perfect data doesn't exist at this scale.
Collected data for 172 companies across 10 sectors. Cross-referenced at least 2 sources per company for reported metrics. Flagged ~40 estimated NRR values.
Day 4 — Stack decision and project setup
I'd already decided on the tech stack before writing a line of product code:
- Next.js 14 App Router — server components, static generation, fast
- Supabase — Postgres, free tier, instant REST/RPC API
- Tailwind CSS — utility classes, no CSS files
- Vercel — zero-config deployment, preview URLs per commit
The decision took about 20 minutes. I've built 3 other products on this exact stack. I know where the sharp edges are. That familiarity is worth more than any benchmark comparison.
I used Claude to scaffold the initial project structure: Next.js app, Supabase client config, the main database table, and seed script for the CSV data.
Project scaffolded. Supabase table created. CSV data imported via seed script. Basic filter query working against local Supabase instance.
Day 5–6 — Core UI
The main interface is a filterable table with a benchmarking sidebar. I wanted it to feel like a professional data tool — not a startup landing page with a table bolted on.
Key decisions:
- Server-side filtering via Supabase RPC, not client-side array filtering — the dataset is small enough for client-side, but server-side is the right pattern for anything you want to paginate later
- URL state for filters — every filter state is in the URL query string, so results are shareable and bookmarkable
- Benchmarking panel pulls percentile breakdowns dynamically based on current filter context
The filter UI — sector dropdown, ARR tier selector, NRR range slider, sort controls — took about 90 minutes of back-and-forth with Claude to get to production quality. The same work would have taken me a full day solo. AI isn't magic, but for UI plumbing it genuinely accelerates.
Filter UI, results table, benchmarking sidebar, URL state sync, mobile responsive layout. Deployed to Vercel preview URL.
Day 7 — Benchmarking logic
The benchmarking panel is the product's actual value proposition. Raw data is table stakes — contextual interpretation is useful.
For each metric, the panel shows:
- Your number vs. median: how you compare to the 50th percentile for your sector and ARR tier
- Quartile position: 1st (top 25%), 2nd, 3rd, or 4th
- What "good" looks like: the 75th and 90th percentile for your cohort
The percentile calculations run in a Supabase RPC function that takes sector, ARR tier, and metric as parameters and returns the distribution buckets. I wrote the SQL; Claude helped debug a window function edge case where NULL NRR values were affecting the percentile calculations.
Benchmarking panel complete. Percentile calculations validated against manual spot-checks for 3 sectors.
Day 8 — SEO and content
A database product lives or dies on search traffic. The three primary landing pages — NRR benchmarks, Rule of 40, gross margin — needed to be genuinely useful articles, not thin wrapper pages.
I wrote the articles from scratch (they're on this blog too — NRR benchmarks, Rule of 40, gross margin). Each article embeds the live data from the database rather than static screenshots, so the content stays current as I update figures.
Three cornerstone articles written. Dynamic metric embeds working. Metadata, OpenGraph images, sitemap.xml generated.
Day 9 — QA and edge cases
I ran through every filter combination I could think of and found three bugs:
- Percentile calculation breaks when sector has fewer than 10 companies — fixed with a minimum sample size check that falls back to global percentiles
- NRR range slider allows negative values — clamped to 0–200%
- Some company tickers with dots (BRK.B) broke URL state parsing — encoded properly
I built no automated tests for the benchmarking logic. I manually verified ~30 spot-checks. This bit me on day 11 when a data update broke the percentile endpoint silently — caught it via a manual check rather than a test failure. I've added a small integration test suite since.
QA pass complete. 3 bugs fixed. Smoke test on mobile, tablet, desktop.
Day 10 — Data update and final review
I refreshed ~40 data points that had new earnings since I started the build. Updated the CSV, re-seeded Supabase, verified the benchmarking panel recalculated correctly.
Final review: the product did what I wanted it to do. You can look up any of the 172 companies, filter by sector and ARR tier, see where your metrics land against real public company benchmarks, and come away with a number rather than a vague range.
Data refresh complete. Final review. Production deployment approved.
Day 11 — Launch
Deployed to production. Posted on LinkedIn, X, and two SaaS-focused communities. First 200 users in 48 hours without any paid distribution.
The top search landing page within the first week was the NRR benchmarks article, which now ranks on page 1 for several NRR-related queries. The database itself ranks for company-specific queries like "[company name] NRR 2025."
What I'd do differently
I'd spend more time on the data model upfront. I added three new sectors mid-build because my original 7 categories were too coarse. That required a data migration and a UI update that cost half a day.
I'd automate data collection from day one. Manual collection for 172 companies across multiple quarters is untenable. I'm building a scraper pipeline that pulls from SEC EDGAR programmatically — I should have built that first.
I'd write integration tests for any calculation that produces a user-facing number. The silent bug on the percentile endpoint was predictable and preventable.
The actual cost
| Item | Cost | |---|---| | Supabase (free tier) | $0 | | Vercel (hobby plan) | $0 | | Domain (saasdb.app) | $14/yr | | Claude API (development) | ~$8 | | My time (11 days × ~5h) | 55 hours |
The only real cost was time. The product generates traffic and newsletter signups that I can eventually monetize via a premium tier or affiliate relationships with SaaS tooling companies. Break-even on time is the goal, not a VC-scale outcome.
Araho Digital
We build what we write about.
Every technique in this post was used on a real client project. If you're building a SaaS product or internal tool and want it done in weeks, not months — that's what we do.
Fixed price. Fixed scope. Money-back guarantee.
Data sourced from saasdb.app — tracking 172+ public SaaS companies. As of Q1 2025.