DEV Community

Cover image for How I Built a 10,000+ Page SEO Site with Next.js and PostgreSQL
Christina Sanchez
Christina Sanchez

Posted on

How I Built a 10,000+ Page SEO Site with Next.js and PostgreSQL

Most broker comparison sites are pay-to-play. Rankings depend on who pays the most, not actual quality. I built BrokerRank to fix this — a transparent, data-driven comparison of 345+ trading brokers with 10,000+ pages.

Here's how I did it technically.

Tech Stack

  • Next.js 16 (App Router) with TypeScript
  • PostgreSQL (Neon) + Prisma ORM
  • TailwindCSS v4
  • Vercel for hosting
  • ISR (Incremental Static Regeneration) for SEO

The Challenge: 10,000+ Unique Pages

The site has:

  • 345 broker review pages
  • 2,400+ broker sub-pages (fees, regulation, platforms, leverage, deposit, alternatives)
  • 6,500+ comparison pages (broker vs broker)
  • 550+ ranking pages (best forex brokers, best by country, etc.)
  • 300+ glossary terms
  • 250+ guides
  • 25 trading calculators with 60 pair sub-pages

All generated from a single PostgreSQL database.

Programmatic SEO Architecture

Every page type follows the same pattern:

  // app/broker/[slug]/page.tsx
  export const revalidate = 86400 // 24h ISR

  export async function generateStaticParams() {
    const brokers = await prisma.broker.findMany({
      where: { isActive: true },
      select: { slug: true },
    })
    return brokers.map((b) => ({ slug: b.slug }))
  }
Enter fullscreen mode Exit fullscreen mode

At build time, Next.js pre-renders all pages. After 24 hours, ISR regenerates them with fresh data. This gives us:

  • Fast initial load (static HTML from CDN)
  • Fresh content (updated daily)
  • SEO-friendly (fully rendered HTML for crawlers)

The Scoring Algorithm

Each broker gets a weighted score (0-5):

  score = (regulation * 0.25) + (fees * 0.20) + (platform * 0.15) +
          (markets * 0.10) + (trust * 0.15) + (ux * 0.15)
Enter fullscreen mode Exit fullscreen mode

Regulation carries the most weight because for financial products, safety matters most.

Comparison Pages at Scale

6,500+ comparison pages are generated from broker pairs. Instead of pre-rendering all at build time (which would timeout on Vercel), I removed generateStaticParams for comparisons. They render on-demand with ISR caching:

  • First visit: server renders and caches
  • Subsequent visits: served from cache
  • After 24h: regenerated with fresh data

SEO Results

Every page includes:

  • Schema.org structured data (Review, FAQ, Breadcrumb, Article)
  • Dynamic Open Graph images
  • Proper canonical URLs
  • Internal linking between related pages
  • Sitemap with 10,600+ URLs

Lighthouse scores:

  • SEO: 100
  • Best Practices: 100
  • Performance: 74 (Next.js runtime overhead)
  • LCP: 2.0s, CLS: 0, TBT: 70ms

Lessons Learned

  1. Vercel has build limits — 10K+ static pages can timeout. Use ISR for heavy routes.
  2. jsdom doesn't work in Vercel serverless — I had to replace isomorphic-dompurify with a lightweight regex sanitizer.
  3. Prisma needs generate in build — add prisma generate && next build to your build script.
  4. ISR is powerful — you get the best of static and dynamic. Pages are fast AND fresh.

What's Next

  • Waiting for Google to index 10K+ pages (submitted sitemap to Google, Bing, Yandex)
  • Building backlinks and community presence
  • Adding real-time spread data from broker APIs

Check it out: brokerrank.net

Happy to answer questions about the architecture, SEO strategy, or anything else!

Top comments (0)