The Story: From Idea to 20K Monthly Visitors
It started simple. I was working on another project and noticed that many freelancers and small businesses in Spain struggled to find the exact correspondence between IAE and CNAE codes. No free, clear, and fast tool existed.
I decided to build Conversor IAE CNAE in public. No waiting for the "perfect" moment. Just a weekend, Next.js, Supabase, and a dataset of 2,247 official codes (1,187 IAE + 1,060 CNAE).
Today it receives 20K monthly visitors without a single outage.
Why I Chose Next.js 15.5.4 + Supabase
The technical decision was deliberate. I needed:
1. Development speed: Build in days, not weeks 2. Search performance: Users needed instant results 3. Zero infrastructure: No DevOps, no servers to maintain 4. Automatic scaling: Growing without my intervention
Next.js 15.5.4 + Supabase (PostgreSQL 17.6.1) solves all of this. It's not sexy, but it works.
The Real Architecture
``` ┌─────────────────────────────────────────┐ │ Vercel (Next.js 15.5.4) │ │ ├─ API Routes (/api/search) │ │ ├─ Server Components (search) │ │ └─ Static Generation (landing) │ └────────────┬────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ Supabase (PostgreSQL 17.6.1) │ │ ├─ Table: codigos (2,247 records) │ │ ├─ Indexes: code, description │ │ └─ Full-text search enabled │ └─────────────────────────────────────────┘ ```
Simple. Predictable. Scalable.
The Complete Tech Stack
My `package.json` reveals the decisions:
Frontend:
- React 19.1.0 with TypeScript 5 (strong typing from day one)
- TailwindCSS with typography extension
- Lucide React for consistent icons
Data & Analytics:
- @tanstack/react-query: Intelligent search caching
- @supabase/ssr: Auth and sessions without pain
- Microsoft Clarity: Understanding how users interact
- Vercel Analytics: Monitor production performance
Content & Monetization:
- Sanity CMS: Integrated blog (typed with PortableText)
- Google AdSense: Simple monetization without friction
- html2canvas-pro + jsPDF: Export results to PDF
Nothing experimental. Everything battle-tested in production.
How I Optimized for 20K Monthly Visitors
1. Fast Search with Full-Text Search
80% of traffic searches for specific codes. The SQL query is critical:
```sql SELECT * FROM codigos WHERE to_tsvector('spanish', descripcion) @@ plainto_tsquery('spanish', $1) OR codigo ILIKE $2 LIMIT 50; ```
PostgreSQL handles this in milliseconds. No complex indexes. No distributed cache. PostgreSQL is enough.
2. Client-Side Caching
I used React Query to cache searches:
```typescript const { data } = useQuery({ queryKey: ['codigos', searchTerm], queryFn: () => fetch(`/api/search?q=${searchTerm}`).then(r => r.json()), staleTime: 1000 * 60 * 60, // 1 hour }); ```
If someone searches "electricista" at 10:15 and another at 10:17, the second gets the cached result. Supabase load reduction: ~40%.
3. Server Components for Landing
The homepage is static (generated at build time). Zero unnecessary JavaScript. Loads in <800ms.
4. Silent Analytics
Microsoft Clarity + Vercel Analytics without slowing anything down. I understand where people abandon, which searches fail, where they click.
What I Learned: Real Commits
My last 5 commits (January 28, 2026) tell the story:
Commit 1: TypeScript in the Blog ``` fix(blog): resolve TypeScript type error in BlogContentWithAds ```
Strong typing from the start. Prevents production bugs.
Commit 2: AdSense Optimization ``` improve adsense performance ```
Google AdSense can slow things down if you don't optimize it. Lazy loading + async scripts.
Commits 3-5: Mobile UX ``` fix(auth): close mobile menu on auth navigation fix(nav): add viewport units to overlay for full-screen coverage feat(nav): add sticky navigation with always-visible mobile CTA ```
65% of traffic is mobile. These small commits are critical.
Monetization: The Uncomfortable Part
I won't lie about revenue (I don't share specific numbers for privacy), but I can tell you how it works:
1. AdSense: Discreet placement, no saturation 2. Affiliate: Links to accounting firms and business software 3. Premium (future): Export to specific formats, API access
The key is not sacrificing UX for money. The tool is free because it should be. Revenue is secondary.
Why This Scales Without Problems
Vercel
- Automatically deploys on every push
- Auto-scaling without configuration
- Global CDN (important for Spain + Latin America)
Supabase
- Managed PostgreSQL
- Automatic backups
- Performance monitoring included
- Scale when you need it, pay when you use it
Results
- 99.9%+ uptime (Vercel + Supabase are reliable)
- Response time <200ms (p95)
- Zero DevOps maintenance
The Spanish Market: Why It Works
Conversor IAE CNAE exists because:
1. Complex regulation: Freelancers and SMBs need certainty 2. No free alternatives: Everything else is paid or incomplete 3. Natural SEO: "Conversor IAE CNAE" is a real search query 4. Pure utility: Solves a specific problem
It's not viral. It's not exciting. It's useful. And that's enough.
What I'd Do Differently
If I went back:
1. More validation first: Would have validated demand with 10 messages to freelancers 2. Monetization from day one: Test models from day 1 3. Community: Create a Telegram channel for updates
But honestly, the architecture was correct. Next.js + Supabase was the right call.
The Takeaway
You don't need complex infrastructure to scale to 20K monthly visitors. You need:
1. Useful tool: Solves a real problem 2. Right stack: Next.js + Supabase for MVP that scales 3. Simple optimizations: Caching, SQL indexes, lazy loading 4. Patience: Let SEO work
Conversor IAE CNAE is open source on GitHub. Look at the architecture, learn, build something similar.
The next useful tool the Spanish market needs could be yours.
---
Building tools in public? Share your stack in the comments. I'm curious what works in your market.
